I want paint brush functionality on html5 canvas with kineticjs and after reading some tutorials found that a good way to do it is by creating rectangles as various points . But this is creating inconsistency in the line formed . It breaks a lot if mouse is moved fast . Here is link to the fiddle . http://jsfiddle.net/9bGdr/1/
var stage = new Kinetic.Stage({
container:'canvas',
width:500,
height:500
});
var layer = new Kinetic.Layer();
var painting = false ;
stage.add(layer);
var canvas = $(stage.getContent());
var lineThickness = 5 ;
canvas.mousedown(function(e) {
painting = true;
});
canvas.mousemove(function(e) {
if (painting) {
rect = new Kinetic.Rect({
x:e.pageX,
y:e.pageY,
width:lineThickness,
height:lineThickness,
fill:'black',
stroke: 'black',
strokeWidth: lineThickness,
lineJoin: 'round',
lineCap: 'round'
});
layer.add(rect);
layer.batchDraw();
}
});
canvas.mouseup(function(e) {
painting = false ;
});
When your mousemove handler detects a drag distance greater than the size of a rect, you need to draw multiple rects to cover the entire dragged distance.
Here's what to do during each mousemove:
In the illustration below, I dragged the bottom of the T very quickly.
Notice that the code filled in all parts of the drag-line with multiple rects.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/D332T/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.7.2.min.js"></script>
<style>
#canvas{
border:solid 1px #ccc;
margin-top: 0px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container:'canvas',
width:350,
height:350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var painting = false ;
var lineThickness = 5 ;
var startX,startY;
$(stage.getContent()).on('mousedown', function (event) {
var pos=stage.getMousePosition();
startX=parseInt(pos.x);
startY=parseInt(pos.y);
painting = true;
});
$(stage.getContent()).on('mousemove', function (event) {
if(!painting){return;}
var pos=stage.getMousePosition();
var mouseX=parseInt(pos.x);
var mouseY=parseInt(pos.y);
var dx=mouseX-startX;
var dy=mouseY-startY;
var rectCount=Math.sqrt(dx*dx+dy*dy)/lineThickness;
if(rectCount<=1){
rect = new Kinetic.Rect({
x:mouseX,
y:mouseY,
width:lineThickness,
height:lineThickness,
fill:'black',
stroke: 'black',
strokeWidth: lineThickness,
lineJoin: 'round',
lineCap: 'round'
});
layer.add(rect);
}else{
for(var i=0;i<rectCount;i++){
// calc an XY between starting & ending drag points
var nextX=startX+dx*i/rectCount;
var nextY=startY+dy*i/rectCount;
// add a rect at the calculated XY
rect = new Kinetic.Rect({
x:nextX,
y:nextY,
width:lineThickness,
height:lineThickness,
fill:'red',
stroke: 'black',
strokeWidth: lineThickness,
lineJoin: 'round',
lineCap: 'round'
});
layer.add(rect);
}
}
layer.draw();
startX=mouseX;
startY=mouseY;
});
$(stage.getContent()).on('mouseup', function (event) {
startX=null;
startY=null;
painting = false;
});
$(stage.getContent()).on('mouseout', function (event) {
startX=null;
startY=null;
painting = false;
});
}); // end $(function(){});
</script>
</head>
<body>
<div id="canvas"></div>
</body>
</html>
[ Addition based on OP's need for more speed ]
Alternatively, there's a faster and more efficient “sketching” alternative:
The efficiency is that you draw a single polyline instead of many rectangles to cover a drag-line.
Here's a Fiddle: http://jsfiddle.net/m1erickson/CCqhg/
Here's code to sketch with a polyline:
In mousedown: create a new polyline starting at the mousedown coordinate
// a flag we use to see if we're dragging the mouse
var isMouseDown=false;
// a reference to the line we are currently drawing
var newline;
// a reference to the array of points making newline
var points=[];
// On mousedown
// Set the isMouseDown flag to true
// Create a new line,
// Clear the points array for new points
// set newline reference to the newly created line
function onMousedown(event) {
isMouseDown = true;
points=[];
points.push(stage.getMousePosition());
var line = new Kinetic.Line({
points: points,
stroke: "green",
strokeWidth: 5,
lineCap: 'round',
lineJoin: 'round'
});
layer.add(line);
newline=line;
}
In mousemove: add a segment to that line reaching to thecurrent mouse coordinate.
// on mousemove
// Add the current mouse position to the points[] array
// Update newline to include all points in points[]
// and redraw the layer
function onMousemove(event) {
if(!isMouseDown){return;};
points.push(stage.getMousePosition());
newline.setPoints(points);
// use layer.drawScene
// This avoids unnecessarily updating the hit canva
layer.drawScene();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.