You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
4.6 KiB

1 year ago
/*
* Chart.JS Extension
* @version: 1.0.0 (Mon, 25 Nov 2019)
* @requires: Chart.js
* @author: HtmlStream
* @event-namespace: Chart.JS Extension
* @license: Htmlstream Libraries (https://htmlstream.com/)
* Copyright 2019 Htmlstream
*/
function detectRadius(r, h, w, i) {
if (typeof r === 'object') {
if (r[i] > h / 2) {
r[i] = h / 2;
}
if (r[i] > w / 2) {
r[i] = w / 2;
}
return r[i];
} else {
if (r > h / 2) {
r = h / 2;
}
if (r > w / 2) {
r = w / 2;
}
return r;
}
}
window.Chart.elements.Rectangle.prototype.draw = function () {
var ctx = this._chart.ctx,
vm = this._view,
left,
right,
top,
bottom,
signX,
signY,
borderSkipped,
borderWidth,
defaults = {
options: {
cornerRadius: 0
}
},
dataSettings = $(this._chart.canvas).attr('data-hs-chartjs-options') ? JSON.parse($(this._chart.canvas).attr('data-hs-chartjs-options')) : {},
settings = $.extend(true, dataSettings.type, defaults, dataSettings);
borderWidth = vm.borderWidth;
if (!vm.horizontal) {
// bar
left = vm.x - vm.width / 2;
right = vm.x + vm.width / 2;
top = vm.y;
bottom = vm.base;
signX = 1;
signY = bottom > top ? 1 : -1;
borderSkipped = vm.borderSkipped || 'bottom';
} else {
// horizontal bar
left = vm.base;
right = vm.x;
top = vm.y - vm.height / 2;
bottom = vm.y + vm.height / 2;
signX = right > left ? 1 : -1;
signY = 1;
borderSkipped = vm.borderSkipped || 'left';
}
// Canvas doesn't allow us to stroke inside the width so we can
// adjust the sizes to fit if we're setting a stroke on the line
if (borderWidth) {
// borderWidth shold be less than bar width and bar height.
var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom));
borderWidth = borderWidth > barSize ? barSize : borderWidth;
var halfStroke = borderWidth / 2;
// Adjust borderWidth when bar top position is near vm.base(zero).
var borderLeft = left + (borderSkipped !== 'left' ? halfStroke * signX : 0);
var borderRight = right + (borderSkipped !== 'right' ? -halfStroke * signX : 0);
var borderTop = top + (borderSkipped !== 'top' ? halfStroke * signY : 0);
var borderBottom = bottom + (borderSkipped !== 'bottom' ? -halfStroke * signY : 0);
// not become a vertical line?
if (borderLeft !== borderRight) {
top = borderTop;
bottom = borderBottom;
}
// not become a horizontal line?
if (borderTop !== borderBottom) {
left = borderLeft;
right = borderRight;
}
}
ctx.beginPath();
ctx.fillStyle = vm.backgroundColor;
ctx.strokeStyle = vm.borderColor;
ctx.lineWidth = borderWidth;
// Corner points, from bottom-left to bottom-right clockwise
// | 1 2 |
// | 0 3 |
var corners = [
[left, bottom],
[left, top],
[right, top],
[right, bottom]
];
// Find first (starting) corner with fallback to 'bottom'
var borders = ['bottom', 'left', 'top', 'right'],
startCorner = borders.indexOf(borderSkipped, 0);
if (startCorner === -1) {
startCorner = 0;
}
function cornerAt(index) {
return corners[(startCorner + index) % 4];
}
// Draw rectangle from 'startCorner'
var corner = cornerAt(0),
radius,
nextCornerId,
nextCorner,
width,
height,
x,
y;
ctx.moveTo(corner[0], corner[1]);
for (var i = 1; i < 4; i++) {
corner = cornerAt(i);
nextCornerId = i + 1;
if (nextCornerId === 4) {
nextCornerId = 0;
}
nextCorner = cornerAt(nextCornerId);
width = corners[2][0] - corners[1][0];
height = corners[0][1] - corners[1][1];
x = corners[1][0];
y = corners[1][1];
radius = settings.options.cornerRadius;
// Fix radius being too large
ctx.moveTo(x + detectRadius(radius, height, width, typeof radius === 'object' ? 0 : null), y);
ctx.lineTo(x + width - detectRadius(radius, height, width, typeof radius === 'object' ? 0 : null), y);
ctx.quadraticCurveTo(x + width, y, x + width, y + detectRadius(radius, height, width, typeof radius === 'object' ? 0 : null));
ctx.lineTo(x + width, y + height - detectRadius(radius, height, width, typeof radius === 'object' ? 1 : null));
ctx.quadraticCurveTo(x + width, y + height, x + width - detectRadius(radius, height, width, typeof radius === 'object' ? 1 : null), y + height);
ctx.lineTo(x + detectRadius(radius, height, width, typeof radius === 'object' ? 2 : null), y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - detectRadius(radius, height, width, typeof radius === 'object' ? 0 : null));
ctx.lineTo(x, y + detectRadius(radius, height, width, typeof radius === 'object' ? 3 : null));
ctx.quadraticCurveTo(x, y, x + detectRadius(radius, height, width, typeof radius === 'object' ? 3 : null), y);
}
ctx.fill();
if (borderWidth) {
ctx.stroke();
}
};