Reputation: 1051
Question Background:
I am working on a site that, along with other data, draws vertical and horizontal lines on an HTML canvas. That page can be converted to a PDF file when the user wants to download the report. Originally we were using one default style line to draw the graph values. Recently we added a second type of data on the graph and used context.setLineDash([x,x])
to draw dashed lines for the second data type. This works great in browsers. However, when the PDF converter software tries to convert a report with dashed lines, the dashed lines do not show up in the resulting PDF.
After some troubleshooting, I narrowed the problem down to the setLineDash()
property. It appears our converter sofware can understand normal style lines but does not understand the setLineDash()
property. The converter software is several years old and I have been informed that an updated version of the converter will not be bought. I also discovered that there is no support for our version from the creator.
Question: Since I am unable to update our HTML to PDF converter software or get support for it directly, can anyone provide an example of an alternative way to draw a dashed line on a canvas without using setLineDash()
?
EDIT
@K3N,
As per the instructions on the notification I received when you marked this question a duplicate of this other question, I am editing to explain how it is different.
I believe that though the answers to both questions will likely be similar, my question is not a duplicate of the question you indicated. I concede that both questions are asking for a way to draw dashed lines on a canvas. However, the other question is asking how to implement a dashed line by any method. My question specifically states that I cannot use the setLineDash()
property to draw a dashed line. This difference limits the possible answers and I believe it is enough to make both questions sufficiently distinct.
Upvotes: 0
Views: 1362
Reputation: 998
I was also facing a similar problem and I used a different approach to solve this problem. I am posting it in case someone else is having the similar problem.
You can set the stroke pattern on canvas context. Stroke pattern can be any canvas pattern. So here I created an image of 1 pixel height and 6 pixel width. First three pixels were black and other three were white. Now I created the image to create a repeating pattern.
var linePattern;
imageToUsedAsPattern.onload = function() {
linePattern = context.createPattern(imageToUsedAsPattern, "repeat");
context.strokeStyle=linePattern;
}
var imageToUsedAsPattern = new Image();
imageToUsedAsPattern.src = "images/linePatterns.jpg";
Now all the calls to context.stroke will use the pattern to draw strokes. Like if you create a line from the top left corner of the canvas to the bottom right corner it will be a dashed line.
context.moveTo(0,0);
context.lineTo(canvas.width,canvas.height);
context.stroke();
See the full explanation at the following link https://shamailamahmood.blogspot.com/2019/02/html5-canvas-drawing-draw-dotted-or.html
Upvotes: 0
Reputation: 54128
You can create line segments.
The function will draw a dashed line from the info in the dashArr
eg [2,2] will draw a line 2 pixels then a gap 2 pixels and repeat.
function dashedLine(x1,y1,x2,y2,dashArr){
// get the normalised line vector from start to end
var nx = x2 - x1;
var ny = y2 - y1;
const dist = Math.sqrt(nx * nx + ny * ny); // get the line length
nx /= dist;
ny /= dist;
var dashIdx = 0; // the index into the dash array
var i = 0; // the current line position in pixels
ctx.beginPath(); // start a path
while(i < dist){ // do while less than line length
// get the line seg dash length
var dashLen = dashArr[(dashIdx ++) % dashArr.length];
// draw the dash
ctx.moveTo(x1 + nx * i, y1 + ny * i);
i = Math.min(dist,i + dashLen);
ctx.lineTo(x1 + nx * i, y1 + ny * i);
// add the spacing
i += dashArr[(dashIdx ++) % dashArr.length];
if(i <= 0) { // something is wrong so exit rather than endless loop
break;
}
}
ctx.stroke(); // stroke
}
function dashedLine(x1,y1,x2,y2,dashArr){
var nx = x2 - x1;
var ny = y2 - y1;
const dist = Math.sqrt(nx * nx + ny * ny);
nx /= dist;
ny /= dist;
var dashIdx = 0;
var i = 0;
ctx.beginPath();
while(i < dist){
var dashLen = dashArr[(dashIdx ++) % dashArr.length];
ctx.moveTo(x1 + nx * i, y1 + ny * i);
i = Math.min(dist,i + dashLen);
ctx.lineTo(x1 + nx * i, y1 + ny * i);
i += dashArr[(dashIdx ++) % dashArr.length];
if(i <= 0) { // something is wrong so exit rather than endless loop
break;
}
}
ctx.stroke()
}
const ctx = canvas.getContext("2d");
dashedLine(0,0,300,150,[5,5]);
canvas { border : 2px solid black; }
<canvas id="canvas"></canvas>
Upvotes: 4