Javascript 虚线笔划在<;帆布>;

Javascript 虚线笔划在<;帆布>;,javascript,html,canvas,Javascript,Html,Canvas,我想这是不可能设置笔划属性,如CSS,这是很容易的。在CSS中,我们有虚线、虚线、实线,但在画布上绘制线条或笔划时,这似乎不是一个选项。你是如何实现这一点的 我看过一些例子,但对于这样一个愚蠢的函数,它们实在太长了 例如: myContext.lineCap = 'round'; myContext.lineWidth = 4; // Lines 4px wide, dots of diameter 4 myContext.dashedLine(20,150,170,10,[30,10,0,

我想这是不可能设置笔划属性,如CSS,这是很容易的。在CSS中,我们有虚线、虚线、实线,但在画布上绘制线条或笔划时,这似乎不是一个选项。你是如何实现这一点的

我看过一些例子,但对于这样一个愚蠢的函数,它们实在太长了

例如:

myContext.lineCap   = 'round';
myContext.lineWidth = 4; // Lines 4px wide, dots of diameter 4
myContext.dashedLine(20,150,170,10,[30,10,0,10]);

目前HTML5画布规范中不支持虚线

看看这个:

查看Raphael JS库:


有趣的问题!我已经编写了一个虚线的自定义实现;你可以。我采用了Adobe Illustrator的方法,允许您指定一组破折号/间隙长度

对于stackoverflow的后代,以下是我的实现(s/o线宽略有改变):

要交替绘制虚线和圆点,请使用(例如):

“极短”划线长度
0
与圆角线头相结合,将沿直线形成点


如果有人知道访问画布上下文路径的当前点的方法,我很想知道,因为它允许我以
ctx.dashTo(x,y,破折号)的形式编写
而不是要求您在方法调用中重新指定起点。

这个简化版的Phrogz代码利用了Canvas的内置转换功能,还处理特殊情况,例如当dx=0时

var CP = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype;
if (CP.lineTo) {
    CP.dashedLine = function(x, y, x2, y2, da) {
        if (!da) da = [10,5];
        this.save();
        var dx = (x2-x), dy = (y2-y);
        var len = Math.sqrt(dx*dx + dy*dy);
        var rot = Math.atan2(dy, dx);
        this.translate(x, y);
        this.moveTo(0, 0);
        this.rotate(rot);       
        var dc = da.length;
        var di = 0, draw = true;
        x = 0;
        while (len > x) {
            x += da[di++ % dc];
            if (x > len) x = len;
            draw ? this.lineTo(x, 0): this.moveTo(x, 0);
            draw = !draw;
        }       
        this.restore();
    }
}

我认为我的计算是正确的,它看起来还不错。

Mozilla一直在开发一个for画布,因此我们可能会在不久的将来看到它被添加到规范中。

我在Mozilla规范中找到了属性
mozDash
mozDashOffset


它们可能是用来控制破折号的,但我没有用过。

Phroz的解决方案很棒。但当我在应用程序中使用它时,我发现了两个bug

以下代码是Phroz版本的调试(并为可读性而重构)

//修复:减去xStep错误(当x2Math.abs(dy));
变量斜率=(xSlope)?dy/dx:dx/dy;
这个。移动到(x,y);
var Distrimining=Math.sqrt(dx*dx+dy*dy);
var指数=0;
而(分发>=0.1){
var dashLength=Math.min(分发,dashArray[dashIndex%dashCount]);
var step=Math.sqrt(dashLength*dashLength/(1+slope*slope));
if(xSlope){
如果(dx<0)步长=-步长;
x+=阶跃
y+=斜率*阶跃;
}否则{
如果(dy<0)步长=-步长;
x+=斜率*阶跃;
y+=阶跃;
}
此[(dashIndex%2==0)-“lineTo”:“moveTo”](x,y);
分布-=长度;
dashIndex++;
}
}

有一种更简单的方法。根据strokeStyle接受字符串、画布渐变或画布图案。我们只拍一张这样的照片:

  <img src="images/dashedLineProto.jpg" id="cvpattern1" width="32" height="32" />
这并不会产生一条完美的虚线,但它非常简单且可修改。当然,当你画的不是水平线或垂直线时,结果可能会变得不完美,虚线模式可能会有所帮助


请记住,当您试图在代码中使用来自外部源的IMG时,SOP适用。

中有对它的支持

似乎
ctx.webkitLineDash
以前工作过,但他们删除了它,因为它有一些


say
ctx.setLineDash([5,10])但它似乎还没有在任何地方实现。

目前至少setLineDash([5,10])与Chrome和ctx兼容。mozDash=[5,10]与FF兼容:

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

if ( ctx.setLineDash !== undefined )   ctx.setLineDash([5,10]);
if ( ctx.mozDash !== undefined )       ctx.mozDash = [5,10];

ctx.beginPath();              
ctx.lineWidth="2";
ctx.strokeStyle="green";
ctx.moveTo(0,75);
ctx.lineTo(250,75);
ctx.stroke();

设置为null将使直线变为实线。

我修改了
虚线
函数以添加对偏移的支持。如果浏览器支持
ctx.setLineDash
ctx.lineDashOffset
,它将使用本机虚线

例如:

var CP=window.canvasrendingcontext2d&&canvasrendingcontext2d.prototype;
如果(CP.lineTo){
CP.dashedLine=CP.dashedLine | |函数(x,y,x2,y2,da,偏移){
如果(!da)da=[10,5];
如果(!offset)offset=0;
if(CP.setLineDash&&typeof(CP.lineDashOffset)=“number”){
这是save();
这是setLineDash(da);
this.lineDashOffset=偏移量;
这个。移动到(x,y);
这个.lineTo(x2,y2);
这个.restore();
返回;
}
这是save();
变量dx=(x2-x),
dy=(y2-y);
var len=Math.sqrt(dx*dx+dy*dy);
var rot=数学常数2(dy,dx);
这个。翻译(x,y);
这个。移动到(0,0);
这个。旋转(腐烂);
var dc=da.长度;
var di=0;
var模式长度=0;
对于(变量i=0;i=startPos){
如果(偏移量>=startPos+da[startSegment%dc]){
startPos+=da[startSegment%dc];
startSegment++;
}否则{
offset=Math.abs(offset-startPos);
打破
}
如果(起始段>100)中断;
}
draw=startSegment%2==0;
x=0;
di=起始段;
while(len>x){
var间隔=da[di++%dc];
if(x<偏移量){
  <img src="images/dashedLineProto.jpg" id="cvpattern1" width="32" height="32" />
  var img=document.getElementById("cvpattern1");
  var pat=ctx.createPattern(img,"repeat");
  ctx.strokeStyle = pat;
  ctx.strokeRect(20,20,150,100);
ctx.mozDash = [5,10];
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");

if ( ctx.setLineDash !== undefined )   ctx.setLineDash([5,10]);
if ( ctx.mozDash !== undefined )       ctx.mozDash = [5,10];

ctx.beginPath();              
ctx.lineWidth="2";
ctx.strokeStyle="green";
ctx.moveTo(0,75);
ctx.lineTo(250,75);
ctx.stroke();
var CP = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype;
if (CP.lineTo) {

    CP.dashedLine = CP.dashedLine || function (x, y, x2, y2, da, offset) {

        if (!da) da = [10, 5];
        if (!offset) offset = 0;

        if (CP.setLineDash && typeof (CP.lineDashOffset) == "number") {
            this.save();
            this.setLineDash(da);
            this.lineDashOffset = offset;

            this.moveTo(x, y);
            this.lineTo(x2, y2);

            this.restore();
            return;
        }


        this.save();
        var dx = (x2 - x),
            dy = (y2 - y);
        var len = Math.sqrt(dx * dx + dy * dy);
        var rot = Math.atan2(dy, dx);
        this.translate(x, y);
        this.moveTo(0, 0);
        this.rotate(rot);
        var dc = da.length;
        var di = 0;

        var patternLength = 0;
        for (var i = 0; i < dc; i++) {
            patternLength += da[i];
        }
        if (dc % 2 == 1) {
            patternLength *= 2;
        }

        offset = offset % patternLength;
        if (offset < 0) {
            offset += patternLength;
        }

        var startPos = 0;
        var startSegment = 0;
        while (offset >= startPos) {



            if (offset >= startPos + da[startSegment % dc]) {
                startPos += da[startSegment % dc];
                startSegment++;
            } else {
                offset = Math.abs(offset - startPos);
                break;
            }


            if (startSegment > 100) break;
        }
        draw = startSegment % 2 === 0;
        x = 0;
        di = startSegment;


        while (len > x) {
            var interval = da[di++ % dc];
            if (x < offset) {
                interval = Math.max(interval - offset, 1);
                offset = 0;
            }

            x += interval;
            if (x > len) x = len;
            draw ? this.lineTo(x, 0) : this.moveTo(x, 0);
            draw = !draw;
        }
        this.restore();
    };
}