[英]How to draw a line in canvas with a background image
I'm trying to draw a line in canvas (which I can do), but I want to put a repeating pattern on the line using a background image (unless there is another way to put a repeating background image on a line in canvas?). 我正在尝试在画布上画一条线(我可以这样做),但是我想使用背景图像在线条上放置重复图案(除非有另一种方法可以在画布上的线条上放置重复的背景图像? )。
How can I draw a line with a background image? 如何绘制带有背景图像的线?
I understand the concept of clipping, but that only seems to work with shapes... not with a stroke. 我了解剪切的概念,但似乎仅适用于形状...不适用于笔触。 Any ideas? 有任何想法吗?
Here is a jsfiddle of what I was trying http://jsfiddle.net/Z9cd7/ 这是我正在尝试的jsfiddle http://jsfiddle.net/Z9cd7/
function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var radius = 50;
var x = 100;
var dx = 10;
var y = 100;
var dy = 10;
var delay = 10;
var img = new Image();
img.onload = function () {
var canvas1 = document.getElementById("image");
var ctxImg = canvas1.getContext("2d");
ctxImg.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
/*
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.beginPath();
ctx.arc(100, 100, radius, 0, 2 * Math.PI, false);
ctx.clip();
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
ctx.restore();
*/
ctx.moveTo(0,0)
ctx.lineTo(100,100)
ctx.lineWidth = 10;
ctx.stroke()
ctx.clip();
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
ctx.restore();
//animate();
}
img.src = "http://lh3.ggpht.com/_Z-i7eF_ACGI/TRxpFywLCxI/AAAAAAAAAD8/ACsxiuO_C1g/house%20vector.png";
I see two solutions : 我看到两个解决方案:
The code is this one, basically you want a varLine with w1 = w2 (same start / end thickness) ; 代码是这样的,基本上你想要一个varLine w1 = w2(相同的开始/结束厚度);
// varLine : draws a line from A(x1,y1) to B(x2,y2)
// that starts with a w1 width and ends with a w2 width.
// relies on fillStyle for its color.
// ctx is a valid canvas's context2d.
function varLine(ctx, x1, y1, x2, y2, w1, w2) {
var dx = (x2 - x1);
var dy = (y2 - y1);
w1 /= 2; // we only use w1/2 and w2/2 for computations.
w2 /= 2;
// length of the AB vector
var length = Math.sqrt(sq(dx) + sq(dy));
if (!length) return; // exit if zero length
var shiftx = -dy * w1 / length; // compute AA1 vector's x
var shifty = dx * w1 / length; // compute AA1 vector's y
ctx.beginPath();
ctx.moveTo(x1 + shiftx, y1 + shifty);
ctx.lineTo(x1 - shiftx, y1 - shifty); // draw A1A2
shiftx = -dy * w2 / length; // compute BB1 vector's x
shifty = dx * w2 / length; // compute BB1 vector's y
ctx.lineTo(x2 - shiftx, y2 - shifty); // draw A2B1
ctx.lineTo(x2 + shiftx, y2 + shifty); // draw B1B2
ctx.closePath(); // draw B2A1
ctx.fill();
}
Updated fiddle is here : http://jsfiddle.net/gamealchemist/Z9cd7/1/ 更新的小提琴在这里: http : //jsfiddle.net/gamealchemist/Z9cd7/1/
Edit : fiddle for the image with repetitions : http://jsfiddle.net/gamealchemist/Z9cd7/2/ 编辑:为重复的图像提琴: http : //jsfiddle.net/gamealchemist/Z9cd7/2/
I bit late but as there is no need to use neither clipping or calculating vectors you could perhaps consider using the built-in support for this (which is faster) by simply setting a stroke style with an image pattern as style: 我有点晚了,但是由于不需要使用裁剪或计算向量,您可以考虑通过简单地将笔触样式设置为图像样式作为样式来使用内置的支持(速度更快):
var pattern = ctx.createPattern(image, 'repeat'); /// create pattern
ctx.strokeStyle = pattern; /// set as stroke style
ctx.moveTo(10, 10);
ctx.lineTo(200, 200);
ctx.lineWidth = 10;
ctx.stroke(); /// strokes with the image as background
If you want to change the pattern size just change the size of the canvas (" image
") you're using in this case: 如果要更改图案大小,只需更改在这种情况下使用的画布(“ image
”)的大小即可:
<canvas id="image" width=100 height=100></canvas>
And with modification in your onload
handler so image is scaled to fit the canvas: 并在onload
处理程序中进行了修改,因此图像被缩放以适合画布:
ctxImg.drawImage(img, 0, 0, canvas1.width, canvas1.height);
If you need to adjust the position of the pattern when drawing you can use translate()
using a delta value which you first translate with and then subtract to the positions of the lines you want to draw with the pattern - that will keep the lines in the same position as before translating but move the pattern itself: 如果在绘制时需要调整图案的位置,则可以使用delta值来使用translate()
,首先将其转换,然后减去要使用图案绘制的线条的位置-这样可以使线条保持在与平移之前的位置相同,但会移动图案本身:
ctx.translate(dx, dy);
ctx.moveTo(x1 - dx, y1 - dy);
ctx.lineTo(x2 - dx, y2 - dy);
...
[ Using an image to draw a line ] [使用图像画线]
You can use this utility function to determine any percentage point along a line segment: 您可以使用此实用程序功能来确定线段上的任何百分比:
function getLineXYatPercent(startPt,endPt,percent) {
var dx = endPt.x-startPt.x;
var dy = endPt.y-startPt.y;
var X = startPt.x + dx*percent;
var Y = startPt.y + dy*percent;
return( {x:X,y:Y} );
}
After that it's just a bit-of-math to repeatedly position your image along each line segement: 之后,沿着每条线段重复定位图像只是一点点的事:
var dx=points[i].x-points[i-1].x;
var dy=points[i].y-points[i-1].y;
var length=Math.sqrt(dx*dx+dy*dy);
var pctImage=imgWidth/length;
for(var pct=pctImage/2;pct<1.00;pct+=pctImage){
var pos=getLineXYatPercent(points[i-1],points[i],pct);
ctx.drawImage(img,0,0,img.width,img.height,pos.x,pos.y,imgWidth,imgHeight);
}
Demo: http://jsfiddle.net/m1erickson/R278u/ 演示: http : //jsfiddle.net/m1erickson/R278u/
Code: 码:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: lightgray; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();
var isDown=false;
var points=[];
points.push({x:0,y:0});
points.push({x:100,y:125});
points.push({x:200,y:75});
points.push({x:300,y:100});
imgWidth=20;
imgHeight=20;
var img=new Image();
img.onload=function(){
draw();
}
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/house%20vector.png";
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.beginPath();
ctx.moveTo(points[0].x,points[0].y);
for(var i=1;i<points.length;i++){
var p=points[i];
var dx=points[i].x-points[i-1].x;
var dy=points[i].y-points[i-1].y;
var length=Math.sqrt(dx*dx+dy*dy);
var pctImage=imgWidth/length;
for(var pct=pctImage/2;pct<1.00;pct+=pctImage){
var pos=getLineXYatPercent(points[i-1],points[i],pct);
ctx.drawImage(img,0,0,img.width,img.height,pos.x,pos.y,imgWidth,imgHeight);
}
}
}
function getLineXYatPercent(startPt,endPt,percent) {
var dx = endPt.x-startPt.x;
var dy = endPt.y-startPt.y;
var X = startPt.x + dx*percent;
var Y = startPt.y + dy*percent;
return( {x:X,y:Y} );
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Aren't you just drawing over everything with the second drawImage call? 您不是通过第二个drawImage调用来绘制所有内容吗?
edit : you are, but that's not what you mean, try beginning and closing the path 编辑:是的,但这不是您的意思,请尝试开始和结束路径
ctx.beginPath();
ctx.moveTo(0,0)
ctx.lineTo(100,100)
ctx.lineTo(100,0);
ctx.closePath()
ctx.lineWidth = 10;
ctx.stroke();
ctx.clip();
ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.