2016-08-18 84 views
1

假设我有一个HTML5画布(在这种情况下使用fabric.js),并且我想在画布上更改光标以表示所选画笔大小和颜色。我认为应该有办法通过动态地改变SVG的属性(大小&颜色)来做到这一点,所以我们不必使用多个图像。任何想法,如果这是可能的?JavaScript - 动态创建SVG并修改光标

var canvas = new fabric.Canvas(c, { 
      isDrawingMode: true, 
      freeDrawingCursor: 'url("img/cursor.svg"), auto' 
}); 

回答

2

我认为freeDrawingCursor只是寻找普通的css属性名称。下面是如何有一个布对象的例子代表了光标的大小和颜色:

var canvas = new fabric.Canvas('c', { 
 
    isDrawingMode: true, 
 
    freeDrawingCursor: 'none' 
 
}); 
 

 
canvas.freeDrawingBrush.width = 10; 
 
canvas.freeDrawingBrush.color = '#9f9'; 
 

 
var mousecursor = new fabric.Circle({ 
 
    left: 0, 
 
    top: 0, 
 
    radius: canvas.freeDrawingBrush.width/2, 
 
    fill: canvas.freeDrawingBrush.color, 
 
    originX: 'right', 
 
    originY: 'bottom', 
 
}) 
 

 
canvas.add(mousecursor); 
 

 
canvas.on('mouse:move', function(obj) { 
 
    mousecursor.top = obj.e.y - mousecursor.radius; 
 
    mousecursor.left = obj.e.x - mousecursor.radius; 
 
    canvas.renderAll() 
 
}) 
 

 
canvas.on('mouse:out', function(obj) { 
 
    // put circle off screen 
 
    mousecursor.top = -100; 
 
    mousecursor.left = -100; 
 
    canvas.renderAll() 
 
})
canvas { 
 
    border: 1px solid #ccc; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.3/fabric.js"></script> 
 

 
<canvas id="c" width="600" height="600"></canvas>

+0

这是一个非常伟大的想法!我在我自己的应用程序中发现圆形光标未与绘制线的实际位置对齐,而且在退出绘制模式时光标仍然保留。你只是将不透明度设置为0或什么? http://codepen.io/paulcredmond/pen/GqLmgb –

+1

注意设置originX和originY的代码。我注意到需要这些设置才能使圆圈与绘图输出发生的位置相同。在鼠标上设置不透明度为0:可能会有效。更理想的解决方案可能是从鼠标上的画布上移除对象:退出但只保留对它的引用,所以当您回过画布时,可以将其添加回来。 – StefanHayden

+0

似乎没有'mouse:exit'功能。任何想法如何做到这一点? –

1

我一直在寻找同样的,发现我的方式对这一问题。不幸的是,STHayden的解决方案并不适合我。所以我修改了一下,并提出了下面的代码。它使用两个画布层,底部用于绘制,“游标”的顶部。现在工作很适合我,也许有人会发现它的帮助:)

//drawing layer 
 
var canvas = new fabric.Canvas("draw", { 
 
    isDrawingMode: true, 
 
    freeDrawingCursor: 'none' 
 
}); 
 
//mouse cursor layer 
 
var cursor = new fabric.StaticCanvas("cursor"); 
 

 
canvas.freeDrawingBrush.width = 20; 
 
canvas.freeDrawingBrush.color = '#ff0000'; 
 

 
var cursorOpacity = .5; 
 
//create cursor and place it off screen 
 
var mousecursor = new fabric.Circle({ 
 
    left: -100, 
 
    top: -100, 
 
    radius: canvas.freeDrawingBrush.width/2, 
 
    fill: "rgba(255,0,0," + cursorOpacity + ")", 
 
    stroke: "black", 
 
    originX: 'center', 
 
    originY: 'center' 
 
}); 
 

 
cursor.add(mousecursor); 
 

 
//redraw cursor on new mouse position when moved 
 
canvas.on('mouse:move', function (evt) { 
 
    var mouse = this.getPointer(evt.e); 
 
    mousecursor 
 
    .set({ 
 
     top: mouse.y, 
 
     left: mouse.x 
 
    }) 
 
    .setCoords() 
 
    .canvas.renderAll(); 
 
}); 
 

 
//put cursor off screen again when mouse is leaving 
 
canvas.on('mouse:out', function() { 
 
    mousecursor 
 
    .set({ 
 
     top: mousecursor.originalState.top, 
 
     left: mousecursor.originalState.left 
 
    }) 
 
    .setCoords() 
 
    .canvas.renderAll(); 
 
}); 
 

 
//while brush size is changed show cursor in center of canvas 
 
document.getElementById("size").oninput = function() { 
 
    var size = parseInt(this.value, 10); 
 
    mousecursor 
 
    .center() 
 
    .set({ 
 
     radius: size/2 
 
    }) 
 
    .setCoords() 
 
    .canvas.renderAll(); 
 
}; 
 

 
//after brush size has been changed move offscreen, update brush size 
 
document.getElementById("size").onchange = function() { 
 
    var size = parseInt(this.value, 10); 
 
    canvas.freeDrawingBrush.width = size; 
 
    mousecursor 
 
    .set({ 
 
     left: mousecursor.originalState.left, 
 
     top: mousecursor.originalState.top, 
 
     radius: size/2 
 
    }) 
 
    .setCoords() 
 
    .canvas.renderAll(); 
 
}; 
 

 
//change mousecursor opacity 
 
document.getElementById("opacity").onchange = function() { 
 
    cursorOpacity = this.value; 
 
    var fill = mousecursor.fill.split(","); 
 
    fill[fill.length-1] = cursorOpacity + ")"; 
 
    mousecursor.fill = fill.join(","); 
 
}; 
 

 
//change drawing color 
 
document.getElementById("color").onchange = function() { 
 
    canvas.freeDrawingBrush.color = this.value; 
 
    var bigint = parseInt(this.value.replace("#", ""), 16); 
 
    var r = (bigint >> 16) & 255; 
 
    var g = (bigint >> 8) & 255; 
 
    var b = bigint & 255; 
 
    mousecursor.fill = "rgba(" + [r,g,b,cursorOpacity].join(",") + ")"; 
 
};
#cont { 
 
    position: relative; 
 
    width: 500px; 
 
    height: 500px; 
 
} 
 

 
canvas { 
 
    border: 1px solid; 
 
} 
 

 
#cont canvas, .canvas-container { 
 
    position: absolute!important; 
 
    left: 0!important; 
 
    top: 0!important; 
 
    width: 100%!important; 
 
    height: 100%!important; 
 
} 
 

 
#cursor { 
 
    pointer-events: none!important; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.4/fabric.min.js"></script> 
 
Color: <input id="color" type="color" value="#ff0000"><br/> 
 
Brush size: <input id="size" type="range" min="1" max="100" step="1" value="20"><br/> 
 
Brush opacity: <input id="opacity" type="number" min="0" max="1" step="0.1" value="0.5"><br/> 
 
<div id="cont"> 
 
    <canvas id="draw" width="500" height="500"></canvas> 
 
    <canvas id="cursor" width="500" height="500"></canvas> 
 
</div>

+0

感谢您发布您的解决方案。实际上我得出了上述几乎相同的结论,但我不必在画布上创建额外的“图层”。 –

+1

@PaulRedmond:是的,你不需要第二层。我使用它,因为我在绘图层上执行图像处理,并在那里有光标(例如“看到”它的像素)不会有帮助。随着两层一切都大大分开:) – Fidel90

+1

好点。我正在考虑保存或序列化图像,因为我必须每次隐藏光标。与重置画布时相同,我必须再次创建光标。 –