Konva JS - How add Shapes custom with input value - html5-canvas

I'm trying to add a custom element using buttons, when I add a new element and change the radius of the input, it changes the radius of all the circles in the square. I don't know what to do, I've already seen and revised my code and I couldn't find a solution.
I tried to find in the documentation what may be happening, I imagine the reason is that Scene func updates all objects. The big point is that if I add a circle when I create the layer it does not update when I add it via the button.
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/konva#8.0.1/konva.min.js"></script>
<meta charset="utf-8" />
<title>Konva Custom Shape Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
</style>
</head>
x <input type="number" name="x" id="x">
y <input type="number" name="y" id="y">
raio <input type="number" name="raio" id="raio">
<button onclick="addCircle()">addQuad</button>
<body>
<div id="container"></div>
<script>
function addCircle(){
x1 = document.getElementById('x').value
y1 = document.getElementById('y').value
raio2 = document.getElementById('raio').value
var triangle = new Konva.Shape({
sceneFunc: function (context, shape) {
context.beginPath();
context.arc(y1, x1, raio2, 2 * Math.PI, 0);
context.closePath();
// (!) Konva specific method, it is very important
context.fillStrokeShape(shape);
},
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4,
draggable: true,
});
// add the triangle shape to the layer
layer.add(triangle);
layer.draw();
}
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
var layer = new Konva.Layer();
/*
* create a triangle shape by defining a
* drawing function which draws a triangle
*/
// add the layer to the stage
stage.add(layer);
</script>
</body>
</html>

I was cleaning your code and the error disappeared ...
Not exactly sure what was wrong, but it works, see my code below
Here are some things I found sticky in your code:
The arc you had context.arc(y1, x1, raio2 I think it should be x then y
I split the function into two one that collects the elements another that draws
The new function takes a few more parameters to control color and stroke width
I'm also drawing a couple of circles to show it working
function addCircle() {
x = document.getElementById('x').value
y = document.getElementById('y').value
r = document.getElementById('raio').value
circle(x, y, r, '#00D2FF', 4)
}
function circle(x, y, r, fillColor, strokeWidth) {
layer.add(new Konva.Shape({
sceneFunc: function(context, shape) {
context.beginPath();
context.arc(x, y, r, 2 * Math.PI, 0);
context.closePath();
context.fillStrokeShape(shape);
},
fill: fillColor,
stroke: 'black',
strokeWidth: strokeWidth,
draggable: true,
}));
layer.draw();
}
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
var layer = new Konva.Layer();
stage.add(layer);
circle(100, 100, 8, "red", 2)
circle(200, 90, 6, "blue", 1)
input {
width: 80px;
}
<script src="https://unpkg.com/konva#8.0.1/konva.min.js"></script>
x <input type="number" name="x" id="x" value="20">
y <input type="number" name="y" id="y" value="20">
raio <input type="number" name="raio" id="raio" value="10">
<button onclick="addCircle()">addQuad</button>
<div id="container"></div>

Related

Fabric.js / fabricjs in Svelte, is there any workaround?

I have tried this code in REPL but couldn't find any working example. I am trying to free drawing on canvas using fabric pencil brush, however, this is only a rectangle:
<script>
const fabric = () => {
fabric = new window.fabric();
}
function drawMD(){
let canvas = new fabric.Canvas('c')
let rect = new fabric.Rect({
left:150, top, 150, fill: 'red, width: 200, height: 200, angle: 45
})
canvas.add(rect)
}
</script>
<svelte:head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/500/fabric.min.js" on:load={fabric}></script>
</svelte:head>
<div className="MarkdownEditor">
<canvas id="c" width="600" height="600" style="border:1px solid #000000;" on:click={drawMD}>
</canvas>
</div>
You don't need the window part, there are some typos in the Rect object and className won't work in Svelte. If you want to directly draw without having to click on the canvas, you can do this inside onMount. Here's a working REPL
(when opening the REPL there might be an errorfabric is not defined - just move the <svelte:head> one line down, then it's working...)
<svelte:head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/500/fabric.min.js"></script>
</svelte:head>
<script>
import {onMount} from 'svelte'
onMount(() => {
let canvas = new fabric.Canvas('c2')
let rect = new fabric.Rect({
left:120, top: 10, fill: 'teal', width: 150, height: 150, angle: 45
})
canvas.add(rect)
})
function drawMD(){
let canvas = new fabric.Canvas('c')
let rect = new fabric.Rect({
left:120, top: 10, fill: 'red', width: 150, height: 150, angle: 45
})
canvas.add(rect)
}
</script>
<div class="MarkdownEditor">
<canvas id="c" width="250" height="250" style="border:1px solid #000000;" on:click={drawMD}></canvas>
</div>
<canvas id="c2" width="250" height="250" style="border:1px solid #000000;"></canvas>

Fabric.js - Rotate change the position of object

I would rotate an object on FabricJS canvas, but when I rotate, its position changed. And I can't use center origin, just left/top, beacuse I save coordinates to database reference by left/top position.
Can you help me? Any idea?
Here is the example.
Thanks
var canvas = window._canvas = new fabric.Canvas('c');
canvas.add(new fabric.Triangle({
width: 100,
height: 100,
left: 0,
top: 0,
angle: 0,
fill: '#00AC6B'
}));
function rotateObject(angleOffset) {
var obj = canvas.getActiveObject();
if (!obj) return;
var angle = obj.getAngle() + angleOffset;
angle = angle > 360 ? 90 : angle < 0 ? 270 : angle;
obj.setAngle(angle).setCoords();
canvas.renderAll();
document.getElementById('log').innerHTML += 'Left: ' + obj.left + ', top: ' + obj.top + '<br>';
}
fabric.util.addListener(document.getElementById('rotate-left'), 'click', function () {
rotateObject(-90);
});
fabric.util.addListener(document.getElementById('rotate-right'), 'click', function () {
rotateObject(90);
});
canvas {
border: 1px solid #999;
}
.log {
height: 220px;
overflow: auto;
border: 1px solid #999;
padding: 5px;
margin-top: 10px;
}
<script src="https://rawgit.com/kangax/fabric.js/1.x/dist/fabric.js"></script>
<canvas id="c" width="400" height="400"></canvas>
<div>
<button id="rotate-left">Rotate left</button>
<button id="rotate-right">Rotate right</button>
</div>
<div id="log" class="log">
</div>

FabricJS image object clipTo shape object issue

Why this clipTo method doesn't work on the latest fabricjs version, which you could resize the object container and the image inside it. Also you able to move the container object and image object.
var imgInstance = new fabric.Image(img, {
width: instanceWidth,
height: instanceHeight,
top: (canvas.getHeight() / 2 - instanceHeight / 2),
left: (canvas.getWidth() / 2 - instanceWidth / 2),
originX: 'left',
originY: 'top'
});
canvas.add(imgInstance);
imgInstance.clipTo = function(ctx) {
/* image clipping method doesn't work on latest fabricjs version*/
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
clippingRect.render(ctx);
ctx.restore();
};
http://jsfiddle.net/efmbrm4v/2/
Or is their another approach shape object inside is the image object.
There is some caching issue with the latest version of FabricJS. To get around that, you need to set objectCaching property to false for the rectangle object.
$(document).ready(function() {
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
});
var canvas = new fabric.Canvas('myCanvas');
var clippingRect = new fabric.Rect({
left: 100,
top: 100,
width: 100,
height: 100,
fill: 'transparent',
opacity: 1,
objectCaching: false //<-- set this
});
canvas.add(clippingRect);
function handleImage(e) {
var reader = new FileReader();
reader.onload = function(event) {
var img = new Image();
img.onload = function() {
var instanceWidth, instanceHeight;
instanceWidth = img.width;
instanceHeight = img.height;
var imgInstance = new fabric.Image(img, {
width: instanceWidth,
height: instanceHeight,
top: (canvas.getHeight() / 2 - instanceHeight / 2),
left: (canvas.getWidth() / 2 - instanceWidth / 2),
originX: 'left',
originY: 'top'
});
canvas.add(imgInstance);
imgInstance.clipTo = function(ctx) {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
clippingRect.render(ctx);
ctx.restore();
};
canvas.renderAll();
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.13/fabric.min.js"></script>
<canvas id="myCanvas" width="400" height="300" style="border: 1px solid black"></canvas>
<br />
<label>Choose a File:</label>
<br/>
<br />
<input type="file" id="imageLoader" name="imageLoader" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

KineticJS draw Image inside a circle

I am trying to place an image inside a circle using:
var gArrow2 = new Image();
gArrow2.src = '../../Content/images/green_s.png';
var circle2 = new Kinetic.Circle({
drawFunc: function(canvas) {
var context = canvas.getContext();
context.drawImage(gArrow2, 256, 256, 11, 23);
context.beginPath();
context.arc(256, 256, this.getRadius(), 0, 2 * Math.PI, false);
context.lineWidth = this.getStrokeWidth();
context.strokeStyle = this.getStroke();
context.stroke();
},
x: 256,
y: 256,
radius: 70,
stroke: '#00ffff',
strokeWidth: 4,
opacity: 0.5
});
layer2.add(circle2);
It does not work! I would appreciate your suggestions, thanks in advance.
You have to give gArrow2 time to load. You do this through gArrow2.onload.
Always put gArrow2.src after it's onload.
Then put any code that uses gArrow2 inside the onload function.
[Edit to add layer2.draw()]
I plugged your code in and got it working.
Looks like all that was needed was layer2.draw();
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/Qgnkx/
<!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://www.html5canvastutorials.com/libraries/kinetic-v4.3.3-beta.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 600,
height: 600
});
var layer2 = new Kinetic.Layer();
stage.add(layer2);
var gArrow2 = new Image();
gArrow2.onload=function(){
var circle2 = new Kinetic.Circle({
drawFunc: function(canvas) {
var context = canvas.getContext();
context.drawImage(gArrow2, 256, 256, 11, 23);
context.beginPath();
context.arc(256, 256, this.getRadius(), 0, 2 * Math.PI, false);
context.lineWidth = this.getStrokeWidth();
context.strokeStyle = this.getStroke();
context.stroke();
},
x: 256,
y: 256,
radius: 70,
stroke: '#00ffff',
strokeWidth: 4,
opacity: 0.5
});
layer2.add(circle2);
layer2.draw();
}
gArrow2.src = 'http://dl.dropbox.com/u/139992952/stackoverflow/house1.jpg';
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>

Kineticjs Draggable doesn't work with -ms-transform

I've been trying to use Kineticjs 4.3.3. to create a graphical image and can be dragged across a parent div, but it will not work if the parent div has scalling set under its style properties ( example provided http://jsfiddle.net/kreavie/MZSE9/). Does anyone have any ideas how to get dragging to work when scalling is previously set?
Thanks,
krlib
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=9">
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.0-beta2.js"></script>
<script type="text/javascript">
window.onload = function () {
var par = document.getElementById('frame');
var canvas = document.createElement('div');
canvas.id = "canvas1";
par.appendChild(canvas);
var stage = new Kinetic.Stage({
container: 'canvas1',
width: 500,
height: 500
});
var layer = new Kinetic.Layer();
var triangle = new Kinetic.Polygon({
stroke: "red",
strokeWidth: 4,
points: [60, 100, 90, 100, 90, 140],
draggable: true
});
layer.add(triangle);
stage.add(layer);
}
</script>
</head>
<body >
<div id="frame" style="width: 200px; height: 200px; -ms-transform: scale(0.420091);">
</div>
</body>
</html>
See: http://jsfiddle.net/MZSE9/2/
Your object is local to the canvas element, not to another div in which you apply scaling.
if you want to scale an object, layer, or the entire stage just do:
shape.setScale(xAmount, yAmount);
stage.setScale(xAmount, yAmount);
layer.setScale(xAmount, yAmount);

Resources