I'm trying to make clickable field between all circles. Any idea?
My code: http://jsfiddle.net/LKHSw/
var bok = 700,
width = bok,
height = width,
radius = bok / 5,
stage = new Kinetic.Stage({
container: 'container',
width: width,
height: height
});
var layer = new Kinetic.Layer();
var a = new Kinetic.Circle({
x: bok / 3,
y: bok / 3,
radius: radius,
fill: 'red'
});
var b = new Kinetic.Circle({
x: a.getX() + radius,
y: a.getY(),
radius: radius,
fill: 'blue'
});
var c = new Kinetic.Circle({
x: (b.getX() + a.getX()) / 2,
y: a.getY() + radius,
radius: radius,
fill: 'green'
});
var clipper = function (ctx, clipped, clip, self) {
ctx.beginPath();
ctx.arc(clip.getX(), clip.getY(), clip.getRadius(), 0, 2 * Math.PI, false);
ctx.clip();
ctx.beginPath();
ctx.arc(clipped.getX(), clipped.getY(), clipped.getRadius(), 0, 2 * Math.PI, false);
ctx.fillStrokeShape(self);
};
var ab = new Kinetic.Shape({
drawFunc: function (context) {
clipper(context, a, b, this);
},
fill: 'yellow'
});
var bc = new Kinetic.Shape({
drawFunc: function (context) {
clipper(context, b, c, this);
},
fill: 'pink'
});
var ca = new Kinetic.Shape({
drawFunc: function (context) {
clipper(context, c, a, this);
},
fill: 'orange'
});
layer.add(a);
layer.add(b);
layer.add(c);
layer.add(ab);
layer.add(bc);
layer.add(ca);
var hover = function (shape) {
var defaultColor;
shape.on('mouseover', function () {
defaultColor = shape.getFill();
shape.setFill('black');
layer.draw();
}).on('mouseout', function () {
shape.setFill(defaultColor);
layer.draw();
});
};
hover(a);
hover(b);
hover(c);
hover(ab);
hover(bc);
hover(ca);
stage.add(layer);
This is a crude implementation using your clipper function: (updated fiddle)
var clipper2 = function (ctx, clipped, clip1, clip2, self) {
ctx.beginPath();
ctx.arc(clip1.getX(), clip1.getY(), clip1.getRadius(), 0, 2 * Math.PI, false);
ctx.clip();
ctx.beginPath();
ctx.arc(clip2.getX(), clip2.getY(), clip2.getRadius(), 0, 2 * Math.PI, false);
ctx.clip();
ctx.beginPath();
ctx.arc(clipped.getX(), clipped.getY(), clipped.getRadius(), 0, 2 * Math.PI, false);
ctx.fillStrokeShape(self);
};
And declare your shape as below -
var abc = new Kinetic.Shape({
drawFunc: function (context) {
clipper2(context, c, a, b, this);
},
fill: 'white'
});
Related
i want to draw a line beetween a circle everytime i add a circle on konva js. and the circle is dragable. so i want the line follow the circle when i drag it. How to do it? or maybe i'm doing it wrong. Here my code https://jsfiddle.net/nutsi/2L7v6hy3/13/
var stage = new Konva.Stage({
height: window.innerHeight * 0.85,
width: window.innerWidth * 0.85,
container: "konva"
});
var layer = new Konva.Layer();
stage.on("click", function(){
var points = [];
var pos = this.getRelativePointerPosition();
var dot = new Konva.Circle({
x: pos.x,
y: pos.y,
fill: 'red',
radius: 5,
id: "seljal",
draggable: true
});
layer.add(dot)
var a = layer.find("#seljal")
for(let x = 0; x < a.length; x++){
points.push(a[x].attrs.x, a[x].attrs.y)
}
var line = new Konva.Line({
points: points,
stroke: "red",
strokeWidth: 2,
dash: [5, 5],
opacity: 1,
closed: !0,
id: "line"
})
var b = layer.find("#line")[0]
if(b) b.destroy();
layer.add(line);
})
stage.add(layer);
stage.draw();
I am trying to click at the corner of the polygon and then logging the label which I have clicked.
I am attaching an event listener on canvas clicked and then logging the coordinates but they are not exactly the same which they were while drawing so how to get the intersection point(that is label) on click.
My code so far
export class AppComponent implements AfterViewInit {
coordinates = [
{
x:10,
y:10,
label:'A'
},
{
x:10,
y:250,
label:'B'
},
{
x:250,
y:250,
label:'C'
},
{
x:250,
y:150,
label:'D'
},
{
x:400,
y:150,
label:'E'
},
{
x:400,
y:10,
label:'F'
}
]
/** Template reference to the canvas element */
#ViewChild('canvasEl') canvasRef: ElementRef;
/** Canvas 2d context */
private context: CanvasRenderingContext2D;
constructor() {}
ngAfterViewInit() {
this.setDummyRoofLayout();
}
setDummyRoofLayout() {
let ctx: CanvasRenderingContext2D = this.canvasRef.nativeElement.getContext(
'2d'
);
let ctx2: CanvasRenderingContext2D = this.canvasRef.nativeElement.getContext(
'2d'
);
let label: CanvasRenderingContext2D = this.canvasRef.nativeElement.getContext(
'2d'
);
ctx.strokeStyle = '#EE9723';
ctx.lineWidth = 2;
ctx.beginPath();
ctx2.beginPath();
ctx2.fillStyle = '#EE9723';
ctx2.arc(10, 10, 10, 0, 2 * Math.PI);
ctx2.fill();
ctx2.beginPath();
ctx2.arc(10, 250, 10, 0, 2 * Math.PI);
ctx2.fill();
ctx2.beginPath();
ctx2.arc(250, 250, 10, 0, 2 * Math.PI);
ctx2.fill();
ctx2.beginPath();
ctx2.arc(250, 150, 10, 0, 2 * Math.PI);
ctx2.fill();
ctx2.beginPath();
ctx2.arc(400, 150, 10, 0, 2 * Math.PI);
ctx2.fill();
ctx2.beginPath();
ctx2.arc(400, 10, 10, 0, 2 * Math.PI);
ctx2.fill();
ctx.moveTo(10, 10);
ctx.lineTo(10, 250);
ctx.lineTo(250, 250);
ctx.lineTo(250, 150);
ctx.lineTo(400, 150);
ctx.lineTo(400, 10);
ctx.lineTo(10, 10);
ctx.stroke();
label.beginPath();
label.moveTo(10, 10);
label.fillStyle = 'white';
label.textAlign = 'center';
label.textBaseline = 'middle';
label.font = '.75rem Arial';
label.fillText('A', 10, 10);
label.fillText('B', 10, 250);
label.fillText('C', 250, 250);
label.fillText('D', 250, 150);
label.fillText('E', 400, 150);
label.fillText('F', 400, 10);
label.stroke();
ctx.canvas.addEventListener(
'click',
this.onclick.bind(this)
);
}
onclick(e){
console.log(e);
let xAxis = e.layerX ;
let yAxis = e.layerY;
this.coordinates.forEach(element=>{
if(element.x+4 <xAxis && element.y+4>yAxis){
alert('label A clicked');
}
})
}
}][1]][1]
online editor link
You can do this with a bit of Math:
intersect(point, coord) {
return Math.sqrt((point.x-coord.x) ** 2 + (point.y - coord.y) ** 2) < 10; //where 10 = your circle radius
}
onclick(e: MouseEvent){
const pos = {
x: e.layerX,
y: e.layerY
};
this.coordinates.forEach(coord => {
if (this.intersect(pos, coord)) {
alert('clicked: ' + coord.label);
}
})
}
Stack Blitz Demo
I'm using Konva JS in my project. I'm adding a shape on a button click which is draggable. On click of the shape i need to get X and Y positions of the shape. getX and getY functions are returning the original X and Y. How can I update the X and Y after dragging.
Example code below.
var stage = new Konva.Stage({
container: 'canvas', // id of container <div>
width: 500,
height:300
});
jQuery("#add-shape").click(function(){
addShape();
});
var addShape = function(){
console.log("add shape");
var layer = new Konva.Layer();
var parentContainer = new Konva.Rect({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
width: 200,
height: 60,
cornerRadius: 10,
fill: '#ccc'
});
var smallCircle = new Konva.Circle({
x: stage.getWidth() / 2 + 200,
y: stage.getHeight() / 2 + 30,
radius: 15,
fill: "#F2784B",
stroke: "white",
strokeWidth: 2
});
smallCircle.on('click', function() {
console.log(this.getX(),this.getY());
addArrow(this.getX(),this.getY());
//get current X and Y here instead of origina X and Y
});
layer.add(parentContainer);
layer.add(smallCircle);
layer.draggable('true');
stage.add(layer);
}
var addArrow = function(arrowX,arrowY){
var connectorLayer = new Konva.Layer();
var connector = new Konva.Arrow({
points: [arrowX,arrowY,arrowX+10,arrowY],
pointerLength: 4,
pointerWidth: 4,
fill: 'black',
stroke: 'black',
strokeWidth: 2
});
connectorLayer.add(connector);
stage.add(connectorLayer);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/konvajs/konva/1.0.2/konva.min.js"></script>
<button id="add-shape">
Add shape
</button>
<div id="canvas">
</div>
If you need to get a mouse position you can use:
smallCircle.on('click', function() {
console.log(stage.getPointerPosition());
});
box.on('mouseout', function () {
document.body.style.cursor = 'default';
console.log(box.attrs.x);
console.log(box.attrs.y);
});
I don't know if this is what you're looking for and it's too late but i'll post it anyway for future developers..
Lets say this is my watermark image inside the layer and bluh bluh and i want it's position getX() and getY(): I use the group like this:
First the regular stuff to add the image:
function update(activeAnchor) {
var group = activeAnchor.getParent();
var topLeft = group.get('.topLeft')[0];
var topRight = group.get('.topRight')[0];
var bottomRight = group.get('.bottomRight')[0];
var bottomLeft = group.get('.bottomLeft')[0];
var image = group.get('Image')[0];
var anchorX = activeAnchor.getX();
var anchorY = activeAnchor.getY();
// update anchor positions
switch (activeAnchor.getName()) {
case 'topLeft':
topRight.setY(anchorY);
bottomLeft.setX(anchorX);
break;
case 'topRight':
topLeft.setY(anchorY);
bottomRight.setX(anchorX);
break;
case 'bottomRight':
bottomLeft.setY(anchorY);
topRight.setX(anchorX);
break;
case 'bottomLeft':
bottomRight.setY(anchorY);
topLeft.setX(anchorX);
break;
}
image.position(topLeft.position());
var width = topRight.getX() - topLeft.getX();
var height = bottomLeft.getY() - topLeft.getY();
if (width && height) {
image.width(width);
image.height(height);
}
}
function addAnchor(group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
var anchor = new Konva.Circle({
x: x,
y: y,
stroke: '#666',
fill: '#ddd',
strokeWidth: 2,
radius: 8,
name: name,
draggable: true,
dragOnTop: false
});
anchor.on('dragmove', function () {
update(this);
layer.draw();
});
anchor.on('mousedown touchstart', function () {
group.setDraggable(false);
this.moveToTop();
});
anchor.on('dragend', function () {
group.setDraggable(true);
layer.draw();
});
// add hover styling
anchor.on('mouseover', function () {
var layer = this.getLayer();
document.body.style.cursor = 'pointer';
this.setStrokeWidth(4);
layer.draw();
});
anchor.on('mouseout', function () {
var layer = this.getLayer();
document.body.style.cursor = 'default';
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
var stage = new Konva.Stage({
container: 'container',
width: 595,
height: 842
});
var layer = new Konva.Layer();
stage.add(layer);
//WaterMark
var WaterMarkImg = new Konva.Image({
width: 595,
height: 842
});
var WaterMarkGroup = new Konva.Group({
x: 0,
y: 0,
draggable: true
});
layer.add(WaterMarkGroup);
WaterMarkGroup.add(WaterMarkImg);
addAnchor(WaterMarkGroup, 0, 0, 'topLeft');
addAnchor(WaterMarkGroup, 595, 0, 'topRight');
addAnchor(WaterMarkGroup, 595, 842, 'bottomRight');
addAnchor(WaterMarkGroup, 0, 842, 'bottomLeft');
var imageObj1 = new Image();
imageObj1.onload = function () {
WaterMarkImg.image(imageObj1);
layer.draw();
};
imageObj1.src = "some image Url";
and this is simply the getX(): very simple
var x = WaterMarkGroup.getX();
alert(x);
I hope this helps anyone looking for it.
This is not the exact answer for the question. point is the draggable shape.
point.on('dragmove', (t) => {
console.log("dragmove", t.target.x(), t.target.y());
});
use shape.getAttr("x") and shape.getAttr("y"), following is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!--mobile friendly-->
<meta name="viewport" content="width=device-width, user-scalable=yes">
</head>
<body>
<div id="c"></div>
<script type="module">
import "../../node_modules/konva/konva.js"
var stage = new Konva.Stage({
container: "#c",
width: 500,
height: 500
})
var layer = new Konva.Layer()
stage.add(layer)
var c = (x, y) => {
return new Konva.Circle({
x: x,
y: y,
stroke: "lightblue",
strokeWidth: 2,
radius: 10,
draggable: true
})
}
let c1 = c(50, 50)
layer.add(c1)
var c2 = c(100, 50)
layer.add(c2)
c1.on("dragmove", () => {
c2.setAttr("y", c1.getAttr("y"))
})
layer.draw()
</script>
</body>
</html>
I know you can draw a wedge using a Kinetic.Wedge:
var compassArc = new Kinetic.Wedge({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
angleDeg: 60,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
rotationDeg: -90
});
This draws a "pizza slice" with a black outline around the whole thing. I just want the "crust" of the pizza, with no straight lines coming back to the center of the circle. How can I do this?
Setting the fill to null removes the red but leaves the outline.
How about creating a custom shape fot this using arc?
http://www.html5canvastutorials.com/tutorials/html5-canvas-arcs/
Please keep in mind that not to close path and not to fill strokes. if so, you will get what you want. It is a KineticJS object, so that you can drag around if you want.
Here is the working example.
http://jsfiddle.net/bighostkim/WzxxH/
var arc = new Kinetic.Shape({
drawFunc: function(canvas) {
var context = canvas.getContext();
var x = stage.getWidth() / 2;
var y = stage.getHeight()/2;
var radius = 70;
var startAngle = 1 * Math.PI;
var endAngle = 0 * Math.PI;
var context = canvas.getContext('2d');
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, false);
//context.closePath();
canvas.stroke(this);
},
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4,
draggable:true
});
allenhwkim answer is a bit outdated and has some problems. For example the kinetic dash array would not work. So here is a revised version:
var arc = new Kinetic.Shape({
x: 100,
y: 100,
stroke: '#000',
strokeWidth: 4,
dash: [8, 4],
drawFunc: function(context) {
var radius = 50;
var startAngle = 1 * Math.PI;
var endAngle = 0 * Math.PI;
context.beginPath();
context.arc(0, 0, radius, startAngle, endAngle, false);
context.fillStrokeShape(this);
},
draggable:true
});
There is a Kinetic.Arc class which you can use.
Make outerRadius equal to innerRadius and you will get what you want.
this.arc = new Kinetic.Arc({
innerRadius: 90,
outerRadius: 90,
stroke: 'red',
strokeWidth: 2,
angle: 60,
rotationDeg: 210
});
How can I make a mouseover function in JavaScript less resource-intensive? I used a way where one function activates another (mouse over) and this function activates the first (mouseout). I used Kinetic.js, but I would also like to have a solution with another library.
I'd like to use it later with other options for mouseover functions.
My code:
<head>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.0.0.js"></script>
<script>
var scolor = "green"
var ncolor = "red"
function changeCircle (circleLayer, nx, ny, nradius, nfill, nstroke, nstrokeWidth) {
var stage = new Kinetic.Stage("container", 578, 200);
var context = circleLayer.getContext();
circleLayer.clear();
var ncircle = new Kinetic.Circle({
x: nx ,
y: ny ,
radius: nradius ,
fill: nfill ,
stroke: nstroke ,
strokeWidth: nstrokeWidth
});
circleLayer.add(ncircle);
stage.add(circleLayer);
ncircle.on("mouseout", function(){
drawCircle (nx, ny, nradius, scolor, nstroke, nstrokeWidth);
});
}
function drawCircle(sx, sy, sradius, sfill, sstroke, sstrokeWidth) {
var stage = new Kinetic.Stage("container", 578, 200);
var circleLayer = new Kinetic.Layer();
circleLayer.clear();
//circle
var scircle = new Kinetic.Circle({
x: sx ,
y: sy ,
radius: sradius ,
fill: sfill ,
stroke: sstroke ,
strokeWidth: sstrokeWidth
});
scircle.on("mouseover", function() {
changeCircle(circleLayer, sx, sy, sradius, "red", sstroke, sstrokeWidth);
});
circleLayer.add(scircle);
stage.add(circleLayer);
}
window.onload = function(){
drawCircle (200, 100, 50, "green", "black", 3);
};
</script>
</head>
<body>
<div id="container">
</div>
</body>
Before mouseover and mouseout, clear div(container) Tag.
<head>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.0.0.js"></script>
<script>
var scolor = "green"
var ncolor = "red"
function changeCircle(circleLayer, nx, ny, nradius, nfill, nstroke, nstrokeWidth) {
var stage = new Kinetic.Stage({ container: "container", width: 578, height: 200 });
var context = circleLayer.getContext();
circleLayer.clear();
var ncircle = new Kinetic.Circle({
x: nx,
y: ny,
radius: nradius,
fill: nfill,
stroke: nstroke,
strokeWidth: nstrokeWidth
});
circleLayer.add(ncircle);
stage.add(circleLayer);
ncircle.on("mouseout", function() {
document.getElementById("container").innerHTML = "";
drawCircle(nx, ny, nradius, scolor, nstroke, nstrokeWidth);
});
}
function drawCircle(sx, sy, sradius, sfill, sstroke, sstrokeWidth) {
var stage = new Kinetic.Stage({ container: "container", width: 578, height: 200 });
var circleLayer = new Kinetic.Layer();
//circle
var scircle = new Kinetic.Circle({
x: sx,
y: sy,
radius: sradius,
fill: sfill,
stroke: sstroke,
strokeWidth: sstrokeWidth
});
scircle.on("mouseover", function() {
document.getElementById("container").innerHTML = "";
changeCircle(circleLayer, sx, sy, sradius, "red", sstroke, sstrokeWidth);
});
circleLayer.add(scircle);
stage.add(circleLayer);
}
window.onload = function() {
drawCircle(200, 100, 50, "green", "black", 3);
};
</script>
</head>
<body>
<div id="container">
</div>
</body>
OR use mouseout event in same function
<head>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.0.0.js"></script>
<script>
var scolor = "green"
var ncolor = "red"
function drawCircle(sx, sy, sradius, sfill, sstroke, sstrokeWidth) {
var stage = new Kinetic.Stage({ container: "container", width: 578, height: 200 });
var circleLayer = new Kinetic.Layer();
//circle
var scircle = new Kinetic.Circle({
x: sx,
y: sy,
radius: sradius,
fill: sfill,
stroke: sstroke,
strokeWidth: sstrokeWidth
});
scircle.on("mouseover", function() {
scircle.attrs.fill = "red";
circleLayer.draw();
});
scircle.on("mouseout", function() {
scircle.attrs.fill = "green";
circleLayer.draw();
});
circleLayer.add(scircle);
stage.add(circleLayer);
}
window.onload = function() {
drawCircle(200, 100, 50, "green", "black", 3);
};
</script>
</head>
<body>
<div id="container">
</div>
</body>