Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Border only top of barchart #5071

Closed
prayer007 opened this issue Dec 22, 2017 · 7 comments · Fixed by #6077
Closed

Border only top of barchart #5071

prayer007 opened this issue Dec 22, 2017 · 7 comments · Fixed by #6077

Comments

@prayer007
Copy link

Is it possible to only draw a border on the top of a barchart like in this example:

grafik

@etimberg
Copy link
Member

You'd probably need to change the draw method on the bar objects. https://github.com/chartjs/Chart.js/blob/master/src/elements/element.rectangle.js#L56

@simonbrunel
Copy link
Member

@etimberg I remember a PR about that feature, but can't find it. I think we should support:

borderWidth: {
   top: 1,
   right: 0,
   bottom: 0,
   left: 0
}

as we do for some padding options (could be the same for borderColor). Then we could deprecate the limited borderSkipped option since borderSkipped: 'bottom' (default) would be equivalent to borderWidth.bottom: 0.

@etimberg
Copy link
Member

Agreed, I remember discussing that but I don’t think it was ever implemented. We should do it though

@prayer007
Copy link
Author

That would be a very nice feature to include. Thanky for your help !

1 similar comment
@prayer007
Copy link
Author

That would be a very nice feature to include. Thanky for your help !

@prayer007
Copy link
Author

prayer007 commented Dec 27, 2017

This simple dirty solution also did the job:

Chart.elements.Rectangle.prototype.draw = function() {

			var ctx = this._chart.ctx;
			var vm = this._view;
			var left, right, top, bottom, signX, signY, borderSkipped;
			var borderWidth = vm.borderWidth;

			if(vm.borderSkipped == "showOnlyTop") {
				borderWidth = 0;
			}

			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'];
			var startCorner = borders.indexOf(borderSkipped, 0);
			if (startCorner === -1) {
				startCorner = 0;
			}

			function cornerAt(index) {
				return corners[(0 + index) % 4];
			}


			// Draw rectangle from 'startCorner'
			var corner = cornerAt(0);
			ctx.moveTo(corner[0], corner[1]);

			for (var i = 1; i < 4; i++) {
				corner = cornerAt(i);
				ctx.lineTo(corner[0], corner[1]);
			}

			ctx.fill();
			if (borderWidth) {
				ctx.stroke();
			}

			if(vm.borderSkipped == "showOnlyTop") {

				ctx.beginPath();
				ctx.fillStyle = vm.backgroundColor;
				ctx.strokeStyle = vm.borderColor;
				ctx.lineWidth = borderWidth;

				var corner = cornerAt(1);
				ctx.lineTo(corner[0], corner[1]);
				var corner = cornerAt(2);
				ctx.lineTo(corner[0], corner[1]);

				ctx.stroke();
			}

		}

@benmccann
Copy link
Contributor

Closing as solved

Please ask questions on StackOverflow: https://stackoverflow.com/questions/tagged/chart.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants