Related
I am trying to make a quadratic curved arrow tool.
I was used demo in the following link for creating the tool.
http://kpomservices.com/oldweb/HTML5_Canvas_Curved_Lines.php
i was success to create an tool as I needs.
but I am getting some issues with that.
Hope someone here can help me on that issues...
here is the code I am using for creating the tool ..
line_number++;
var line;
var reinit_stroke = "";
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
function _getQBezierValue(t, p1, p2, p3) {
var iT = 1 - t;
return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3;
}
function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) {
return {
x: _getQBezierValue(position, startX, cpX, endX),
y: _getQBezierValue(position, startY, cpY, endY)
};
}
canvas.on({
'object:selected': onObjectSelected,
'object:moving': onObjectMoving,
'before:selection:cleared': onBeforeSelectionCleared
});
(function drawQuadratic() {
line = new fabric.Path('M 65 0 Q 100, 100, 200, 0', { fill: '', selectable: false,hasBorders: false,hasControls: false,stroke: #000});
line.path[0][1] = posx;
line.path[0][2] = posy;
line.path[1][1] = posx+50;
line.path[1][2] = posy+50;
line.path[1][3] = posx+100;
line.path[1][4] = posy+100;
line.id = line_number;
//line.selectable = false;
canvas.add(line);
canvas.sendBackwards(line);
var pt = getQuadraticCurvePoint(line.path[0][1], line.path[0][2], line.path[1][1], line.path[1][2], line.path[1][3], line.path[1][4], 0.5);
var p1 = makeCurvePoint(pt.x, pt.y, null, line, null)
p1.name = "p1";
p1.id = line_number;
canvas.add(p1);
var p0 = makeCurveCircle(posx, posy, line, p1, null);
p0.name = "p0";
p0.id = line_number;
canvas.add(p0);
var p2 = makeArrow(posx+100, posy+100, null, p1, line);
p2.name = "p2";
p2.id = line_number;
canvas.add(p2);
var dx = line.path[1][3] - posx;
var dy = line.path[1][4] - posy;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
p2.setAngle(angle + 90);
p2.setCoords();
canvas.bringToFront(p2);
canvas.bringToFront(p0);
canvas.bringToFront(p1);
line.p2 = p2;
})();
function makeArrow(left, top, line1, line2, line3) {
var c = new fabric.Triangle({
width: 5,
height: 5,
left: left+5,
top: top+5,
strokeWidth: 10,
fill: #000,
opacity: 1,
stroke: #000
});
c.hasBorders = c.hasControls = false;
c.angle = 90;
c.line1 = line1;
c.line2 = line2;
c.line3 = line3;
return c;
}
function makeCurveCircle(left, top, line1, line2, line3) {
var c = new fabric.Circle({
radius: 5,
left: left,
top: top,
strokeWidth: 10,
fill: #000,
stroke: #000
});
c.hasBorders = c.hasControls = false;
c.line1 = line1;
c.line2 = line2;
c.line3 = line3;
return c;
}
function makeCurvePoint(left, top, line1, line2, line3) {
var c = new fabric.Circle({
radius: 5,
left: left,
top: top,
strokeWidth: 10,
fill: #000,
opacity: 0,
stroke: #000
});
c.hasBorders = c.hasControls = false;
c.angle = 90;
c.line1 = line1;
c.line2 = line2;
c.line3 = line3;
return c;
}
var prevselobj;
function onObjectSelected(e) {
var activeObject = e.target;
reinit_stroke = activeObject.stroke;
if (activeObject.name == "p0" || activeObject.name == "p2") {
if (prevselobj) {
prevselobj.line2.animate('opacity', '0', {
duration: 200,
onChange: canvas.renderAll.bind(canvas),
});
prevselobj.line2.selectable = false;
}
activeObject.line2.animate('opacity', '1', {
duration: 200,
onChange: canvas.renderAll.bind(canvas),
});
activeObject.line2.selectable = true;
prevselobj = activeObject;
}
}
function onBeforeSelectionCleared(e) {
var activeObject = e.target;
if (activeObject.name == "p0" || activeObject.name == "p2") {
activeObject.line2.animate('opacity', '0', {
duration: 200,
onChange: canvas.renderAll.bind(canvas),
});
activeObject.line2.selectable = false;
}
else if (activeObject.name == "p1") {
activeObject.animate('opacity', '0', {
duration: 200,
onChange: canvas.renderAll.bind(canvas),
});
activeObject.selectable = true;
}
}
function onObjectMoving(e) {
if (e.target.name == "p0" || e.target.name == "p2") {
var p = e.target;
var curvedline;
if (p.line1) {
p.line1.path[0][1] = p.left;
p.line1.path[0][2] = p.top + p.height/2;
curvedline = p.line1;
} else if (p.line3) {
p.line3.path[1][3] = p.left;
if(p.line3.path[0][2] <= p.line3.path[1][4])
p.line3.path[1][4] = p.top - p.height/2;
if(p.line3.path[0][2] > p.line3.path[1][4])
p.line3.path[1][4] = p.top + p.height/2;
p.line3.setCoords();
curvedline = p.line3;
}
if (curvedline) {
curvedline.setCoords();
var pt = getQuadraticCurvePoint(curvedline.path[0][1], curvedline.path[0][2], curvedline.path[1][1], curvedline.path[1][2], curvedline.path[1][3], curvedline.path[1][4], 0.5);
p.line2.left = pt.x;
p.line2.top = pt.y;
if (curvedline.p2) {
var pt = getQuadraticCurvePoint(curvedline.path[0][1], curvedline.path[0][2], curvedline.path[1][1], curvedline.path[1][2], curvedline.path[1][3], curvedline.path[1][4], 0.99);
curvedline.p2.left = pt.x;
curvedline.p2.top = pt.y;
var dx = curvedline.path[1][3] - pt.x;
var dy = curvedline.path[1][4] - pt.y;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
curvedline.p2.setAngle(angle + 90);
curvedline.p2.setCoords();
}
p.line2.setCoords();
}
if (e.target.text) {
e.target.text.left = p.left;
e.target.text.top = p.top;
e.target.text.setCoords();
}
} else if (e.target.name == "p1") {
var p = e.target;
if (p.line2) {
p.line2.path[1][1] = p.left;
p.line2.path[1][2] = p.top;
}
curvedline = p.line2;
if (curvedline) {
var pt = getQuadraticCurvePoint(curvedline.path[0][1], curvedline.path[0][2], curvedline.path[1][1], curvedline.path[1][2], curvedline.path[1][3], curvedline.path[1][4], 0.5);
p.left = pt.x;
p.top = pt.y;
p.setCoords();
}
if (curvedline) {
var pt = getQuadraticCurvePoint(curvedline.path[0][1], curvedline.path[0][2], curvedline.path[1][1], curvedline.path[1][2], curvedline.path[1][3], curvedline.path[1][4], 0.99);
curvedline.p2.left = pt.x;
curvedline.p2.top = pt.y;
var dx = curvedline.path[1][3] - pt.x;
var dy = curvedline.path[1][4] - pt.y;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
curvedline.p2.setAngle(angle + 90);
curvedline.p2.setCoords();
}
} else if (e.target.name == "p0" || e.target.name == "p2") {
var p = e.target;
p.line1 && p.line1.set({
'x2': p.left,
'y2': p.top
});
p.line2 && p.line2.set({
'x1': p.left,
'y1': p.top
});
p.line3 && p.line3.set({
'x1': p.left,
'y1': p.top
});
p.line4 && p.line4.set({
'x1': p.left,
'y1': p.top
});
}
p && reinit();
}
function reinit() {
canvas.remove(line);
line = new fabric.Path(line.path, { fill: '',selectable: false });
line.id = line_number;
line.stroke = reinit_stroke;
canvas.add(line);
canvas.sendBackwards(line);
}
canvas.on('mouse:over', function(e) {
if(e.target.type == "path")
{
canvas.sendBackwards(e.target);
}
});
I am using following code for delete the tool.
(Note: this code runs when I click on the delete button.
Delete button deletes the object selected. )
here is the code...
var objs = canvas.getObjects();
if (activeObject) {
active_id = activeObject.get('id');
canvas.forEachObject(function (obj) {
if(obj.get('id') == active_id)
{
if(obj.type == 'path')
{
obj.selectable = true;
canvas.remove(obj);
}
canvas.remove(obj);
}
});
canvas.remove(activeObject);
}
the issue I am getting is after delete this, If I create one other curved arrow in the designer(i.e. without reload the page) and move the nodes then its still showing the old path object which we already deleted.
and If I delete the newly created curved arrow then it removes all path from canvas, In short all Path object behave like one(Hope this is understandable) .
so, the path object is not getting deleted properly it is just getting hidden when I am deleting it. Or may be it is deleted but created again when I am moving another path object..
and if we save the canvas as json then we can see the path objects which are deleted too.
What I need to do is to delete the path object properly and save just the Path object currently showing on the canvas with nodes.
Please tell me if there is some solution for this issues..
Thanks..
I found the solution for the delete curve Issue.
We need to change the code at the reinit() functions.
It was overwrite the line_id to all the line(or say path) in the canvas.
Here is the code to replace with reinit() function..
function reinit() {
var objs = canvas.getObjects();
current_line = canvas.getActiveObject();
canvas.forEachObject(function (obj) {
if(obj.type == 'path' && obj.get("id") == current_line.get("id"))
{
canvas.remove(obj);
line = new fabric.Path(obj.path, { fill: '',selectable: false });
line.id = current_line.get("id");
line.stroke = reinit_stroke;
canvas.add(line);
canvas.sendBackwards(line);
}
});
}
Hope this can be helpful for someone who need this kind of solution..
The code below allows to click on a canvas with a background image and draw a point. I would like to give the change to the user to change the default image, so I have added an input file element. So go to the snippet and follow this steps:
Step 1: click on the first default image "Ziiweb". The coordinate is
shown in the textarea.
Step 2: load/preview a new image using the Browse button, and click on it. As you can see the coordinates of the first image are kept, why?
Hint: after previewing a new image, and click over it, the function mousedown() is called twice.
$.fn.canvasAreaDraw = function (options) {
this.each(function (index, element) {
init.apply(element, [index, element, options]);
});
}
var init = function (index, input, options) {
var points, activePoint, settings;
var $reset, $canvas, ctx, image;
var draw, mousedown, stopdrag, move, resize, reset, resot, rightclick, record, previewImage;
mousedown = function (e) {
console.log('mousedown');
console.log(points);
console.log(points.length);
var x, y, dis, lineDis, insertAt = points.length;
e.preventDefault();
if (!e.offsetX) {
e.offsetX = (e.pageX - $(e.target).offset().left);
e.offsetY = (e.pageY - $(e.target).offset().top);
}
x = e.offsetX;
y = e.offsetY;
points.splice(insertAt, 0, Math.round(x), Math.round(y));
activePoint = insertAt;
$(this).on('mousemove', move);
record();
return false;
};
record = function () {
$(input).val(points.join(','));
};
settings = $.extend({
imageUrl: $(this).attr('data-image-url')
}, options);
points = []; //I expected this to reset the points list!!!, but no....
if (!$(this).is('canvas')) {
$canvas = $('<canvas>');
} else {
$canvas = $(this);
}
ctx = $canvas[0].getContext('2d');
image = new Image();
$(this).prev().prev().val('');
resize = function () {
$canvas.attr('height', image.height).attr('width', image.width);
draw();
};
if (settings.imageUrl) {
image.src = settings.imageUrl;
} else {
image.src = options;
}
$canvas.css({
background: 'url(' + image.src + ')'
});
$(input).after('<br>', $canvas);
$(document).ready(function () {
$canvas.on('mousedown', mousedown);
});
};
//LOAD IMAGE
previewImage = function () {
var aux = $(this).prev();
if (this.files && this.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
aux.canvasAreaDraw(e.target.result);
}
reader.readAsDataURL(this.files[0]);
}
}
$(document).ready(function () {
$('.canvas-area').canvasAreaDraw();
$('.imgInp').on('change', previewImage);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="canvas-area" data-image-url="http://www.ziiweb.com/images/logo.png"></textarea>
<input type='file' class="imgInp" id="jander" />
Because each time you attach a new image, the document.readyevent fires and attaches a new mousedown handler to the canvas.
$.fn.canvasAreaDraw = function (options) {
this.each(function (index, element) {
init.apply(element, [index, element, options]);
});
}
var init = function (index, input, options) {
var points, activePoint, settings;
var $reset, $canvas, ctx, image;
var draw, mousedown, stopdrag, move, resize, reset, resot, rightclick, record, previewImage;
mousedown = function (e) {
console.log('mousedown');
console.log(points);
console.log(points.length);
var x, y, dis, lineDis, insertAt = points.length;
e.preventDefault();
if (!e.offsetX) {
e.offsetX = (e.pageX - $(e.target).offset().left);
e.offsetY = (e.pageY - $(e.target).offset().top);
}
x = e.offsetX;
y = e.offsetY;
points.splice(insertAt, 0, Math.round(x), Math.round(y));
activePoint = insertAt;
$(this).on('mousemove', move);
record();
return false;
};
record = function () {
$(input).val(points.join(','));
};
settings = $.extend({
imageUrl: $(this).attr('data-image-url')
}, options);
points = []; //I expected this to reset the points list!!!, but no....
if (!$(this).is('canvas')) {
$canvas = $('<canvas>');
} else {
$canvas = $(this);
}
ctx = $canvas[0].getContext('2d');
image = new Image();
$(this).prev().prev().val('');
resize = function () {
$canvas.attr('height', image.height).attr('width', image.width);
draw();
};
if (settings.imageUrl) {
image.src = settings.imageUrl;
} else {
image.src = options;
}
$canvas.css({
background: 'url(' + image.src + ')'
});
$(input).after('<br>', $canvas);
$(document).ready(function () {
alert('attaching a new mousedown event!');
$canvas.on('mousedown', mousedown);
});
};
//LOAD IMAGE
previewImage = function () {
var aux = $(this).prev();
if (this.files && this.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
aux.canvasAreaDraw(e.target.result);
}
reader.readAsDataURL(this.files[0]);
}
}
$(document).ready(function () {
$('.canvas-area').canvasAreaDraw();
$('.imgInp').on('change', previewImage);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="canvas-area" data-image-url="http://www.ziiweb.com/images/logo.png"></textarea>
<input type='file' class="imgInp" id="jander" />
The solution being to attach the event somewhere else, or to use a flag.
$.fn.canvasAreaDraw = function (options) {
this.each(function (index, element) {
init.apply(element, [index, element, options]);
});
}
var init = function (index, input, options) {
var points, activePoint, settings;
var $reset, $canvas, ctx, image;
var draw, mousedown, stopdrag, move, resize, reset, resot, rightclick, record, previewImage;
mousedown = function (e) {
console.log('mousedown');
console.log(points);
console.log(points.length);
var x, y, dis, lineDis, insertAt = points.length;
e.preventDefault();
if (!e.offsetX) {
e.offsetX = (e.pageX - $(e.target).offset().left);
e.offsetY = (e.pageY - $(e.target).offset().top);
}
x = e.offsetX;
y = e.offsetY;
points.splice(insertAt, 0, Math.round(x), Math.round(y));
activePoint = insertAt;
$(this).on('mousemove', move);
record();
return false;
};
record = function () {
$(input).val(points.join(','));
};
settings = $.extend({
imageUrl: $(this).attr('data-image-url')
}, options);
points = []; //I expected this to reset the points list!!!, but no....
if (!$(this).is('canvas')) {
$canvas = $('<canvas>');
} else {
$canvas = $(this);
}
ctx = $canvas[0].getContext('2d');
image = new Image();
$(this).prev().prev().val('');
resize = function () {
$canvas.attr('height', image.height).attr('width', image.width);
draw();
};
if (settings.imageUrl) {
image.src = settings.imageUrl;
} else {
image.src = options;
}
$canvas.css({
background: 'url(' + image.src + ')'
});
$(input).after('<br>', $canvas);
$(document).ready(function () {
if(first){
alert('attaching a new mousedown event!');
first= false;
$canvas.on('mousedown', mousedown);
}
});
};
var first = true;
//LOAD IMAGE
previewImage = function () {
var aux = $(this).prev();
if (this.files && this.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
aux.canvasAreaDraw(e.target.result);
}
reader.readAsDataURL(this.files[0]);
}
}
$(document).ready(function () {
$('.canvas-area').canvasAreaDraw();
$('.imgInp').on('change', previewImage);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="canvas-area" data-image-url="http://www.ziiweb.com/images/logo.png"></textarea>
<input type='file' class="imgInp" id="jander" />
How this mouse direction detection would be converted to pure JavaScript?
Question about my logic: Hold the first coordinates in a var and then repeatedly compare the current coordinates with previous one. Is this the best logic for such detection?
http://jsfiddle.net/fallenartist/7pBE7/5/
(function ($) {
var options = {};
var oldx = 0;
var direction = "";
var stop_timeout = false;
var stop_check_time = 150;
$.mousedirection = function (opts) {
var defaults = {};
options = $.extend(defaults, opts);
$(document).bind("mousemove", function (e) {
var activeElement = e.target || e.srcElement;
if (e.pageX > oldx) {
direction = "right";
} else if (e.pageX < oldx) {
direction = "left";
}
clearTimeout(stop_timeout);
stop_timeout = setTimeout(function () {
direction = "stop";
$(activeElement).trigger(direction);
$(activeElement).trigger({
type: "mousedirection",
direction: direction
});
}, stop_check_time);
$(activeElement).trigger(direction);
$(activeElement).trigger({
type: "mousedirection",
direction: direction
});
oldx = e.pageX;
});
}
})(jQuery)
$(function () {
$.mousedirection();
$(".container").bind("mousedirection", function (e) {
$(this).html("Mouse Direction: <b>" + e.direction + "</b>");
});
});
I'm looking for a javascript charting API that would allow user to dynamically modify value points (through drag'n drop) and then provide some callbacks to get those new values.
Do you have any suggestions?
Look at Awesome Free JavaScript Charts review and another one
There is a custom plugin for highcharts that provides dragging of chart points: http://jsfiddle.net/highcharts/AyUbx/:
(function (Highcharts) {
var addEvent = Highcharts.addEvent, each = Highcharts.each;
/**
* Filter by dragMin and dragMax
*/
function filterRange(newY, series, XOrY) {
var options = series.options,
dragMin = options['dragMin' + XOrY],
dragMax = options['dragMax' + XOrY];
if (newY < dragMin) {
newY = dragMin;
} else if (newY > dragMax) {
newY = dragMax;
}
return newY;
}
Highcharts.Chart.prototype.callbacks.push(function (chart) {
var container = chart.container,
dragPoint,
dragX,
dragY,
dragPlotX,
dragPlotY;
chart.redraw(); // kill animation (why was this again?)
addEvent(container, 'mousedown', function (e) {
var hoverPoint = chart.hoverPoint,
options;
if (hoverPoint) {
options = hoverPoint.series.options;
if (options.draggableX) {
dragPoint = hoverPoint;
dragX = e.pageX;
dragPlotX = dragPoint.plotX;
}
if (options.draggableY) {
dragPoint = hoverPoint;
dragY = e.pageY;
dragPlotY = dragPoint.plotY + (chart.plotHeight - (dragPoint.yBottom || chart.plotHeight));
}
// Disable zooming when dragging
if (dragPoint) {
chart.mouseIsDown = false;
}
}
});
addEvent(container, 'mousemove', function (e) {
if (dragPoint) {
var deltaY = dragY - e.pageY,
deltaX = dragX - e.pageX,
newPlotX = dragPlotX - deltaX - dragPoint.series.xAxis.minPixelPadding,
newPlotY = chart.plotHeight - dragPlotY + deltaY,
newX = dragX === undefined ? dragPoint.x : dragPoint.series.xAxis.translate(newPlotX, true),
newY = dragY === undefined ? dragPoint.y : dragPoint.series.yAxis.translate(newPlotY, true),
series = dragPoint.series,
proceed;
newX = filterRange(newX, series, 'X');
newY = filterRange(newY, series, 'Y');
// Fire the 'drag' event with a default action to move the point.
dragPoint.firePointEvent(
'drag', {
newX: newX,
newY: newY
},
function () {
proceed = true;
dragPoint.update([newX, newY], false);
chart.tooltip.refresh(chart.tooltip.shared ? [dragPoint] : dragPoint);
if (series.stackKey) {
chart.redraw();
} else {
series.redraw();
}
});
// The default handler has not run because of prevented default
if (!proceed) {
drop();
}
}
});
function drop(e) {
if (dragPoint) {
if (e) {
var deltaX = dragX - e.pageX,
deltaY = dragY - e.pageY,
newPlotX = dragPlotX - deltaX - dragPoint.series.xAxis.minPixelPadding,
newPlotY = chart.plotHeight - dragPlotY + deltaY,
series = dragPoint.series,
newX = dragX === undefined ? dragPoint.x : dragPoint.series.xAxis.translate(newPlotX, true),
newY = dragY === undefined ? dragPoint.y : dragPoint.series.yAxis.translate(newPlotY, true);
newX = filterRange(newX, series, 'X');
newY = filterRange(newY, series, 'Y');
dragPoint.update([newX, newY]);
}
dragPoint.firePointEvent('drop');
}
dragPoint = dragX = dragY = undefined;
}
addEvent(document, 'mouseup', drop);
addEvent(container, 'mouseleave', drop);
});
/**
* Extend the column chart tracker by visualizing the tracker object for small points
*/
var colProto = Highcharts.seriesTypes.column.prototype,
baseDrawTracker = colProto.drawTracker;
colProto.drawTracker = function () {
var series = this;
baseDrawTracker.apply(series);
each(series.points, function (point) {
point.graphic.attr(point.shapeArgs.height < 3 ? {
'stroke': 'black',
'stroke-width': 2,
'dashstyle': 'shortdot'
} : {
'stroke-width': series.options.borderWidth,
'dashstyle': series.options.dashStyle || 'solid'
});
});
};
})(Highcharts);
im learnig javascript and try to develop a page to draw on. Change colors and linewidth are already in place. Now it is drawing, but just when I move the mouse. I'd like to add also on click on just on move. So I'm able to draw also points. I have put the drawCircle function in the function stopDraw, but this is not working as it should. Any ideas?
Second problem is that, I'd like to draw a circle without stroke. But as soon as I change the lineWidth, also my circle gets a stroke around. Please help...
// Setup event handlers
cb_canvas = document.getElementById("cbook");
cb_lastPoints = Array();
if (cb_canvas.getContext) {
cb_ctx = cb_canvas.getContext('2d');
cb_ctx.lineWidth = 14;
cb_ctx.strokeStyle = "#0052f8";
cb_ctx.lineJoin="round";
cb_ctx.lineCap="round"
cb_ctx.beginPath();
cb_canvas.onmousedown = startDraw;
cb_canvas.onmouseup = stopDraw;
cb_canvas.ontouchstart = startDraw;
cb_canvas.ontouchend = stopDraw;
cb_canvas.ontouchmove = drawMouse;
}
function startDraw(e) {
if (e.touches) {
// Touch event
for (var i = 1; i <= e.touches.length; i++) {
cb_lastPoints[i] = getCoords(e.touches[i - 1]); // Get info for finger #1
}
}
else {
// Mouse event
cb_lastPoints[0] = getCoords(e);
cb_canvas.onmousemove = drawMouse;
}
return false;
}
// Called whenever cursor position changes after drawing has started
function stopDraw(e) {
drawCircle(e);
e.preventDefault();
cb_canvas.onmousemove = null;
}
//Draw circle
function drawCircle(e) {
var canvasOffset = canvas.offset();
var canvasX = Math.floor(e.pageX-canvasOffset.left);
var canvasY = Math.floor(e.pageY-canvasOffset.top);
//var canvasPos = getCoords(e);
cb_ctx.beginPath();
cb_ctx.arc(canvasX, canvasY, cb_ctx.lineWidth/2, 0, Math.PI*2, true);
cb_ctx.fillStyle = cb_ctx.strokeStyle;
cb_ctx.fill();
}
function drawMouse(e) {
cb_ctx.beginPath();
if (e.touches) {
// Touch Enabled
for (var i = 1; i <= e.touches.length; i++) {
var p = getCoords(e.touches[i - 1]); // Get info for finger i
cb_lastPoints[i] = drawLine(cb_lastPoints[i].x, cb_lastPoints[i].y, p.x, p.y);
}
}
else {
// Not touch enabled
var p = getCoords(e);
cb_lastPoints[0] = drawLine(cb_lastPoints[0].x, cb_lastPoints[0].y, p.x, p.y);
}
cb_ctx.stroke();
cb_ctx.closePath();
//cb_ctx.beginPath();
return false;
}
// Draw a line on the canvas from (s)tart to (e)nd
function drawLine(sX, sY, eX, eY) {
cb_ctx.moveTo(sX, sY);
cb_ctx.lineTo(eX, eY);
return { x: eX, y: eY };
}
// Get the coordinates for a mouse or touch event
function getCoords(e) {
if (e.offsetX) {
return { x: e.offsetX, y: e.offsetY };
}
else if (e.layerX) {
return { x: e.layerX, y: e.layerY };
}
else {
return { x: e.pageX - cb_canvas.offsetLeft, y: e.pageY - cb_canvas.offsetTop };
}
}
Your drawCircle function is wrapped in the canvas's onclick event. It should be
function drawCircle(e) {
var canvasOffset = canvas.offset();
var canvasX = Math.floor(e.pageX-canvasOffset.left);
var canvasY = Math.floor(e.pageY-canvasOffset.top);
cb_ctx.beginPath();
cb_ctx.lineWidth = 0;
cb_ctx.arc(canvasX,canvasY,cb_ctx.lineWidth/2,0,Math.PI*2,true);
cb_ctx.fillStyle = cb_ctx.strokeStyle;
cb_ctx.fill();
}
So you'll have to pass the event object from stop draw as well
function stopDraw(e) {
drawCircle(e); //notice the change here
e.preventDefault();
cb_canvas.onmousemove = null;
}
Note that you're also setting you circle's radius to 0 which might be another reason why it's not showing up.
cb_ctx.lineWidth = 0;
cb_ctx.arc(canvasX,canvasY,cb_ctx.lineWidth/2,0,Math.PI*2,true);
0 divided by 2 is always zero. If you don't want to stroke around the circle just don't call stroke(). the drawCircle function isn't causing that, since there's a beginPath() call. I suspect it's because you don't beginPath() before calling stroke() in drawMouse.