Draw arc on mousemove event using Kineticjs - javascript

I have to draw an arc on the layer on mousemove event as per requirement. How can be the parameters in the function context.arc(x,y,startAngel,endAngle,Counterclockwise) fixed according to current mouseposition? My code is as following :
var newarc;
ui.stage.on("mousedown", function () {
var arc = new Kinetic.Shape({
drawFunc: function (canvas) {
var context = canvas.getContext();
var pos = ui.stage.getMousePosition();
var sx = Math.floor(pos.x / ui.scale - ui.stage.getAbsolutePosition().x / ui.scale + ui.stage.getOffset().x);
var sy = Math.floor(pos.y / ui.scale - ui.stage.getAbsolutePosition().y / ui.scale + ui.stage.getOffset().y);
var x = sx;
var y = sy;
var radius = 100;
var startAngle = 1 * Math.PI;
var endAngle = 0.5 * Math.PI;
var context = canvas.getContext('2d');
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, false);
canvas.stroke(this);
},
fill: '#00D2FF',
stroke: 'red',
strokeWidth: 2,
// draggable: false
});
newarc = arc;
moving = true;
ui.myLayer.add(newarc );
});
ui.stage.on("mouseup", function () {
moving = false;
})
ui.stage.on("mousemove", function () {
if (!moving) {
return;
}
var dx = x - startX;
var dy = y - startY
var aradius = Math.sqrt(dx * dx + dy * dy)
newarc.radius = aradius;
ui.myLayer.drawScene();
ui.myLayer.add(newarc);
ui.stage.add(ui.myLayer);
});

Here is how to create a circle by dragging the mouse.
Mousedown:
Create a new circle with its center at the mouse position.
Mousemove:
Change the radius of the circle to the distance between center-circle and the mouse.
Mouseup:
End resizing the circle
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/NQDdE/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<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>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var newArc;
var isDown=false;
stage.on("contentMousedown",function(){
var mouse=stage.getMousePosition();
newArc=new Kinetic.Circle({
x:mouse.x,
y:mouse.y,
radius:.25,
fill:randomColor(),
stroke:"lightgray",
strokeWidth:3
});
layer.add(newArc);
layer.draw();
isDown=true;
});
stage.on("contentMousemove",function(){
if(!isDown){return;}
var mouse=stage.getMousePosition();
var dx=mouse.x-newArc.getX();
var dy=mouse.y-newArc.getY();
var radius=Math.sqrt(dx*dx+dy*dy);
newArc.setRadius(radius);
layer.draw();
});
$(stage.getContent()).on('mouseup', function () {
isDown=false;
newArc=null;
});
function randomColor(){
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
layer.draw();
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>

Related

Konvajs - relative zoom in to pointer, but non-relative zoom out

I am using Konva canvas framework and I want to implement zoom in and zoom out with mouse wheel.
The zoom in should be relative to my cursor pointer, but zoom out should always zoom out to the initial state.
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#7.2.2/konva.min.js"></script>
<meta charset="utf-8" />
<title>Konva Zoom Relative to Stage Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
var layer = new Konva.Layer();
stage.add(layer);
var circle = new Konva.Circle({
x: stage.width() / 2,
y: stage.height() / 2,
radius: 50,
fill: 'green',
});
layer.add(circle);
layer.draw();
var scaleBy = 0.95;
stage.on('wheel', (e) => {
e.evt.preventDefault();
var oldScale = stage.scaleX();
var pointer = stage.getPointerPosition();
var mousePointTo = {
x: (pointer.x - stage.x()) / oldScale,
y: (pointer.y - stage.y()) / oldScale,
};
var newScale =
e.evt.deltaY > 0 ? oldScale * scaleBy : oldScale / scaleBy;
stage.scale({ x: newScale, y: newScale });
var newPos = {
x: pointer.x - mousePointTo.x * newScale,
y: pointer.y - mousePointTo.y * newScale,
};
stage.position(newPos);
stage.batchDraw();
});
</script>
</body>
</html>
So, in the example you can see there is circle green in the center. When client zoom in, I want the zoom to be relative to pointer. But, when zooming out, the zoom won't be relative to pointer, but simply goes back to the initial state (green circle in the center).
So I changed some things, only for demo purpose - but the concept is the same:
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#7.2.2/konva.min.js"></script>
<meta charset="utf-8" />
<title>Konva Zoom Relative to Stage Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
</style>
</head>
<body>
<div id="container"></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
var layer = new Konva.Layer();
stage.add(layer);
var circle = new Konva.Rect({
x: stage.width()/2,
y:stage.height()/2,
width: 50,
height: 50,
fill: 'green',
});
layer.add(circle);
layer.draw();
var scaleBy = 0.99;
stage.on('wheel', (e) => {
e.evt.preventDefault();
var oldScale = stage.scaleX();
var mousePointTo = {
x: stage.getPointerPosition().x / oldScale - stage.x() / oldScale,
y: stage.getPointerPosition().y / oldScale - stage.y() / oldScale
};
var newScale =
e.evt.deltaY > 0 ? oldScale * scaleBy : oldScale / scaleBy;
newScale = Math.max( newScale, 1 );
stage.scale({ x: newScale, y: newScale });
var newPos = {
x:
-(mousePointTo.x - stage.getPointerPosition().x / newScale) *
newScale,
y:
-(mousePointTo.y - stage.getPointerPosition().y / newScale) *
newScale
};
newPos.x = Math.min( newPos.x, 0 );
newPos.x = Math.max( newPos.x, width * ( 1 - newScale ) );
newPos.y = Math.min( newPos.y, 0 );
newPos.y = Math.max( newPos.y, height * ( 1 - newScale ) );
stage.position(newPos);
stage.batchDraw();
});
</script>
</body>
</html>

Draw line from one rectangle to another rectangle ie a setup a connection on JavaScript Canvas

I was trying to build a project in which a user can add a rectangle and set up a connection between them by drawing a line, that is double click on one rectangle to start and double-clicking on the other rectangle to finish the line. The rectangle can be moved anywhere in the canvas and lines should be intact.This code helps me to add the feature rectangle move I have added 2 functionality 1) Add rectangle on clicking a button 2) Save the position on clicking save. Now I want to add the lines on the canvas to connect the rectangles
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
background-color: ivory;
}
#canvas {
border: 1px solid red;
}
#canvasimg {
position: absolute;
top: 10%;
left: 52%;
display: none;
}
</style>
</head>
<body>
<h4>Drag one or more of the shapes</h4>
<canvas id="canvas" width=300 height=300></canvas>
<button onclick="addShape()">Add Rectangle</button>
<button onclick="save()">Save</button>
<script src="canvas.js"></script>
</body>
</html>
Script.js
function save() {
var shape = JSON.stringify(shapes, ['x', 'y', 'number'])
console.log(shape);
var blob = new Blob(
[shape],
{ type: "contentType" });
var url = window.URL.createObjectURL(blob);
var anchor = document.createElement("a");
anchor.href = url;
anchor.download = "test.txt";
anchor.click();
window.URL.revokeObjectURL(url);
document.removeChild(anchor);
}
// get canvas related references
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var BB = canvas.getBoundingClientRect();
var offsetX = BB.left;
var offsetY = BB.top;
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
// drag related variables
var dragok = false;
var startX;
var startY;
// an array of objects that define different shapes
var shapes = [];
var number = 0;
// add rectangle on click
function addShape() {
shapes.push({ x: 0, y: 0, width: 30, height: 30, fill: "#444444", isDragging: false, number: number });
draw();
number++;
}
// listen for mouse events
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
canvas.onmousemove = myMove;
// call to draw the scene
draw();
// draw a single rect
function rect(r) {
ctx.fillStyle = r.fill;
ctx.fillRect(r.x, r.y, r.width, r.height);
}
// draw a single rect
function circle(c) {
ctx.fillStyle = c.fill;
ctx.beginPath();
ctx.arc(c.x, c.y, c.r, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
// clear the canvas
function clear() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
}
// redraw the scene
function draw() {
clear();
// redraw each shape in the shapes[] array
for (var i = 0; i < shapes.length; i++) {
// decide if the shape is a rect or circle
// (it's a rect if it has a width property)
if (shapes[i].width) {
rect(shapes[i]);
} else {
circle(shapes[i]);
};
}
}
// handle mousedown events
function myDown(e) {
// tell the browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
// get the current mouse position
var mx = parseInt(e.clientX - offsetX);
var my = parseInt(e.clientY - offsetY);
// test each shape to see if mouse is inside
dragok = false;
for (var i = 0; i < shapes.length; i++) {
var s = shapes[i];
// decide if the shape is a rect or circle
if (s.width) {
// test if the mouse is inside this rect
if (mx > s.x && mx < s.x + s.width && my > s.y && my < s.y + s.height) {
// if yes, set that rects isDragging=true
dragok = true;
s.isDragging = true;
}
} else {
var dx = s.x - mx;
var dy = s.y - my;
// test if the mouse is inside this circle
if (dx * dx + dy * dy < s.r * s.r) {
dragok = true;
s.isDragging = true;
}
}
}
// save the current mouse position
startX = mx;
startY = my;
}
// handle mouseup events
function myUp(e) {
// tell the browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
// clear all the dragging flags
dragok = false;
for (var i = 0; i < shapes.length; i++) {
shapes[i].isDragging = false;
}
}
// handle mouse moves
function myMove(e) {
// if we're dragging anything...
if (dragok) {
// tell the browser we're handling this mouse event
e.preventDefault();
e.stopPropagation();
// get the current mouse position
var mx = parseInt(e.clientX - offsetX);
var my = parseInt(e.clientY - offsetY);
// calculate the distance the mouse has moved
// since the last mousemove
var dx = mx - startX;
var dy = my - startY;
// move each rect that isDragging
// by the distance the mouse has moved
// since the last mousemove
for (var i = 0; i < shapes.length; i++) {
var s = shapes[i];
if (s.isDragging) {
s.x += dx;
s.y += dy;
}
}
// redraw the scene with the new rect positions
draw();
// reset the starting mouse position for the next mousemove
startX = mx;
startY = my;
}
}

How to draw Rhombus/Parallelogram in canvas

I'm a beginner in using the canvas and I need to make shapes on it.
How can I draw a Rhombus/Parallelogram in a canvas?
Something like this:
I have no problem drawing in a rectangle/square with something like this:
var rectangle = new Path2D();
rectangle.rect(0, 0, width, height);
but I have no idea on how to draw a rhombus/parallelogram.
Thanks for anyone that can help.
Drag mouse from top to bottom in straight manner to draw rhombus. Works only ones then refresh browser and try again
let isDrawing = false;
let x = 0;
let y = 0;
var endPoint = [];
var startPoint = [];
const element = document.getElementById('drawFigure');
const ctx1 = element.getContext('2d');
element.addEventListener('mousedown', e => {
x = e.offsetX;
y = e.offsetY;
isDrawing = true;
startPoint.push({
x: e.offsetX,
y: e.offsetY
});
});
element.addEventListener('mousemove', e => {
if (isDrawing === false) {
x = e.offsetX;
y = e.offsetY;
console.log( "x" +x , "y" +y);
}
});
window.addEventListener('mouseup', e => {
if (isDrawing === true) {
x = e.offsetX;
y = e.offsetY;
endPoint.push({
x: e.offsetX,
y: e.offsetY,
fillcolor: 'blue'
});
drawLine();
isDrawing = false;
}
});
function drawLine() {
ctx1.beginPath();
ctx1.moveTo(startPoint[0].x,
startPoint[0].y);
var half = endPoint[0].y - startPoint[0].y
var x1 = startPoint[0].x + half
var y1 = startPoint[0].y + half / 2
ctx1.lineTo(x1, y1)
console.log(x1, y1);
ctx1.moveTo(x1, y1)
ctx1.lineTo(endPoint[0].x,
endPoint[0].y);
ctx1.lineTo(startPoint[0].x - half, y1);
ctx1.lineTo(startPoint[0].x,
startPoint[0].y);
ctx1.stroke();
}
//-------------
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.moveTo(75, 75);
ctx.lineTo(135, 25);
ctx.lineTo(195, 75);
ctx.lineTo(135, 125);
ctx.closePath();
ctx.stroke();
canvas {
border: 2px dotted black;
width: 460px;
height: 330px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="drawFigure" width="560" height="260"></canvas>
<!---------------->
<h3>Hard Stoke 1/2</h3>
<canvas id="myCanvas"> </canvas>
<!-- --->
</body>
</html>

Drawing a circle with random color in canvas on mouse click

I am trying to develop a simple canvas application using html5 and javascript. I want to make a circle depending on the position of mouse click in the canvas. Each time user clicks in canvas a circle should be drawn. Moreover the color of circle needs to be randomly selected. I have written the random color and position function to get x and y position of mouse in canvas. But when i run nothing is happening.
Here is my html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="circle.js"></script>
<style type="text/css">
#testCanvas {
border: 2px solid;
}
</style>
</head>
<body>
<canvas id="testCanvas" width="400" height="400"> </canvas>
</body>
Here's my javascript code:
window.onload = init;
function init() {
// access the canvas element and its context
var canvas = document.getElementById("testCanvas");
var context = canvas.getContext("2d");
var pos = getMousePos(canvas, e);
posx = pos.x;
posy = pos.y;
context.fillStyle = randomColor();
// fill a circle
context.beginPath();
context.arc(posx,posy, 30, 0, 2 * Math.PI, true);
context.fill();
context.closePath();
}
function randomColor() {
var color = [];
for (var i = 0; i < 3; i++) {
color.push(Math.floor(Math.random() * 256));
}
return 'rgb(' + color.join(',') + ')';
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
You need to implement a click handler for the canvas so that every time you click on it you will receive a notification in form of an event:
// access the canvas element and its context
var canvas = document.getElementById("testCanvas");
var context = canvas.getContext("2d");
// add click handler
canvas.onclick = function(e) {
var pos = getMousePos(canvas, e); // get position as before
context.fillStyle = randomColor(); // get the fill color
// fill a circle
context.beginPath(); // now we can draw the circle at click
context.arc(pos.x, pos.y, 30, 0, 2 * Math.PI); // use pos object directly like this
context.fill();
// closePath() not needed here and won't work after fill() has been called anyways
}
function randomColor() {
var color = [];
for (var i = 0; i < 3; i++) {
color.push(Math.floor(Math.random() * 256));
}
return 'rgb(' + color.join(',') + ')';
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas {border: 1px solid #999}
<canvas id="testCanvas" width="400" height="400"> </canvas>
Here is another example / way of adding an event handler. You can change 'click' to 'mousemove' and others to try different things.
// access the canvas element and its context
window.onload = init;
function init(){
var canvas = document.getElementById("testCanvas");
var context = canvas.getContext("2d");
function drawCircle(pos,canvas){
posx = pos.x;
posy = pos.y;
context.fillStyle = randomColor();
// fill a circle
context.beginPath();
context.arc(posx,posy, 30, 0, 2 * Math.PI, true);
context.fill();
context.closePath();
}
function randomColor() {
var color = [];
for (var i = 0; i < 3; i++) {
color.push(Math.floor(Math.random() * 256));
}
return 'rgb(' + color.join(',') + ')';
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
} ;
}
canvas.addEventListener('click', function(evt){
var mousePos = getMousePos(canvas,evt);
drawCircle(mousePos,canvas);
},false);
}

Mouse Wheel Zooming

so i'm working on a canvas that you can only drag a image from side to side and use the mouse wheel to re size the image by zooming in and out on it here is the code i have so far please feel free to ask any more details. I'm trying to find a way that's compact to do this and require minimum code.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
<script src="kinetic-v5.1.0.min.js" type="text/javascript"></script>
</head>
<body>
<div id="container"></div>
<script type="text/javascript">
function drawImage(imageObj) {
var stage = new Kinetic.Stage({
container: "container",
width: 1800,
height: 800
});
var layer = new Kinetic.Layer();
// image
var image1 = new Kinetic.Image({
image: imageObj,
x: stage.getWidth() / 2 - 896 / 1,
y: stage.getHeight() / 2 - 255 / 2,
width: 200,
height: 157,
draggable: true,
dragBoundFunc: function (pos) {
if (pos.x < this.minX) { }
this.minX = pos.x;
return {
x: pos.x,
y: this.getAbsolutePosition().y
}
}
});
// add cursor styling
image1.on('mouseover', function() {
document.body.style.cursor = 'pointer';
});
image1.on('mouseout', function() {
document.body.style.cursor = 'default';
});
layer.add(image1);
stage.add(layer);
}
var imageObj = new Image();
imageObj.onload = function() {
drawImage(this);
};
imageObj.src = 'image1.png';
</script>
</body>
</html>
One way would be to use a zoom helper. For example:
var zoomHelper = {
stage: null,
scale: 1,
zoomFactor: 1.1,
origin: {
x: 0,
y: 0
},
zoom: function(event) {
event.preventDefault();
var delta;
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
if (event.originalEvent.detail > 0) {
//scroll down
delta = 0.2;
} else {
//scroll up
delta = 0;
}
} else {
if (event.originalEvent.wheelDelta < 0) {
//scroll down
delta = 0.2;
} else {
//scroll up
delta = 0;
}
}
var evt = event.originalEvent,
mx = evt.clientX - zoomHelper.stage.getX(),
my = evt.clientY - zoomHelper.stage.getY(),
zoom = (zoomHelper.zoomFactor - delta),
newscale = zoomHelper.scale * zoom;
zoomHelper.origin.x = mx / zoomHelper.scale + zoomHelper.origin
.x - mx / newscale;
zoomHelper.origin.y = my / zoomHelper.scale + zoomHelper.origin
.y - my / newscale;
zoomHelper.stage.setOffset({
x: zoomHelper.origin.x,
y: zoomHelper.origin.y
});
zoomHelper.stage.setScale({
x: newscale,
y: newscale
});
zoomHelper.stage.draw();
zoomHelper.scale *= zoom;
}
};
Here is a demo with code you provided in as an example slightly changed.
Try using this full javascript library.

Categories