How can I use the object.set({}) and then have hover area update.
For example when I move a rect to the left, visually the rect has moved but the hover area is still based on the previous left position.
Do I need to do an additional render?
I figured canvas.renderAll() would be enough
Here is a demo
const canvas = new fabric.Canvas(document.getElementById("myCanvas"));
var rect = new fabric.Rect({
width: 100,
height: 100,
fill: "red",
left: 25,
top: 25
});
canvas.add(rect);
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
rect.set({ left: 125 });
canvas.renderAll();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.6/fabric.min.js"></script>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<div id="app"></div>
<button id="btn">move left</button>
<canvas id="myCanvas" width="300" height="200" ></canvas>
</body>
</html>
https://codesandbox.io/s/rlo3ojwvp4
You need to set coordinates after move,check When-to-call-setCoords
DEMO
const canvas = new fabric.Canvas(document.getElementById("myCanvas"));
var rect = new fabric.Rect({
width: 100,
height: 100,
fill: "red",
left: 25,
top: 25
});
canvas.add(rect);
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
rect.set({ left: 125 });
rect.setCoords();
canvas.renderAll();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.6/fabric.min.js"></script>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<div id="app"></div>
<button id="btn">move left</button>
<canvas id="myCanvas" width="300" height="200" ></canvas>
</body>
</html>
Related
I put an image and a textbox on a FabricJS canvas, but only the textbox is rendered. I also tried to export the whole canvas as an image, but still, only the textbox showed up. If I print out all objects on canvas in the console, the image instance is there, but why it's not rendered? Here is the JS Fiddle,
Here is the full HTML file
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.3.1/fabric.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
</head>
<style>
#c {
border: 2px solid black;
}
#render {
border: 2px solid red;
}
</style>
<body>
<h2>This is the test image</h2>
<img id='testImg' src="https://picsum.photos/seed/123/50/50" crossorigin="anonymous">
<h2>Fabric canvas</h2>
<canvas id='c'></canvas>
<h2>Save canvas as an image</h2>
<div id='render'></div>
<script>
var canvas = new fabric.Canvas('c');
canvas.setHeight(200);
canvas.setWidth(200);
//add image
var imgEle = $("#testImg")[0];
var newImg = new fabric.Image(imgEle, {
left: 0,
top:0
});
canvas.add(newImg);
canvas.renderAll();
//add new textbox
var newTextBox = new fabric.Textbox("Hello text box", {
left: 0,
top: 100,
width: 200
});
canvas.add(newTextBox);
canvas.renderAll();
//two objects are stored in canvas
console.log(JSON.stringify(canvas));
//show the canvas image, only one object shows
var canvasUrl = canvas.toDataURL('png');
var canvasImg = $("<img id=canvasImg>");
canvasImg.attr('src', canvasUrl);
canvasImg.appendTo("#render");
</script>
</body>
</html>
In your code you are not waiting for the image to load, so what happens is that the new fabric.Image executes before the image has fully loaded, that is why you only see the text.
We need an onload on the image.
See the code below:
var canvas = new fabric.Canvas('c');
canvas.setHeight(120);
canvas.setWidth(200);
$("#testImg")[0].onload = function () {
var newImg = new fabric.Image(this, { left: 10, top: 10 });
canvas.add(newImg);
canvas.renderAll();
}
var newTextBox = new fabric.Textbox("Hello", { left: 0, top: 70, width: 90 });
canvas.add(newTextBox);
canvas.renderAll();
#c {
border: 2px solid black;
}
#render {
border: 2px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.2/fabric.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
This is the test image
<img id='testImg' src="https://picsum.photos/seed/123/50/50" crossorigin="anonymous">
<canvas id='c'></canvas>
I have a basic Graphics User Interface where if the user clicks "move"
then a div (yellow rectangle) moves across the screen.
However, I want there to be an event based on Where the rectangle is on the page. In example, If the div is at 400px (right) then alert "hey", else, move the div.
here is the moving div
<html>
<head>
<title>Move Div</title>
<script language ="javascript">
<!--
function MoveDiv()
{
div = document.getElementById("myDiv");
div.style.left = parseInt(div.style.left) + 100 + "px";
}
//-->
</script>
</head>
<body>
<input type="button" value="Move Div" onclick="MoveDiv()" />
<div id="myDiv" style="border: 10px solid black; background-color: Yellow; width: 100px; height: 30px; position: absolute; top: 1px; left: 100px;"></div>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
here is the moving div
<html>
<head>
<title>Move Div</title>
<script language ="javascript">
<!--
function MoveDiv(){
if ($('#myDiv').css == marginTop: '-=15px' ) {
div = document.getElementById("myDiv");
div.style.left = parseInt(div.style.left) + 100 + "px";
}}
//-->
</script>
</head>
<body>
<input type="button" value="Move Div" onclick="MoveDiv()" />
<div id="myDiv" style="border: 10px solid black; background-color: Yellow; width: 100px; height: 30px; position: absolute; top: 1px; left: 100px;"></div>
</body>
</html>
errors mostly because im not sure on the syntax :(
hope its help you
You must use var (let, const) when create a new variable
I added CONSTANTS for easy configuration,
isDivCanMoveForward for your:
Where the rectangle is on the page. In example, If the div is at 400px (right) then alert "hey", else, move the div.
var MAX_POSITION_OF_DIV_NODE = 400;
var STEP_OF_DIV_NODE = 100;
var div = document.getElementById("myDiv");
var currentPositionOfDivNode = parseInt(div.style.left, 10);
function MoveDiv() {
currentPositionOfDivNode += STEP_OF_DIV_NODE; // increment
if (!isDivCanMoveForward()) {
return; // stop functinon when div have max position
}
div.style.left = currentPositionOfDivNode + "px";
}
function isDivCanMoveForward() {
if (currentPositionOfDivNode > MAX_POSITION_OF_DIV_NODE) {
currentPositionOfDivNode = MAX_POSITION_OF_DIV_NODE // set max of value
alert('hey')// user message
return false;
}
return true;
}
<html>
<head>
<title>Move Div</title>
</head>
<body>
<input type="button" value="Move Div" onclick="MoveDiv()" />
<div id="myDiv" style="border: 10px solid black; background-color: Yellow; width: 100px; height: 30px; position: absolute; top: 1px; left: 100px;"></div>
</body>
</html>
I'm going to make a twibbon-like website using Fabric.js for my school so students can post a picture and download it with my school campaign image on it and share it to Instagram.
to download the image in high resolution and maintain the canvas to be small enough to fit the screen, I'm using this solution I found from another stackoverflow question here
the problem is the canvas is still small but it push my div or buttons
away by the value of canvas.setWidth or setHeigth.
here's my page looks like.
how can i fix this and bring back my buttons?
here's my code :
.canvas-container canvas {
width: 400px !important;
height: 500px !important;
border: 1px solid blue;
}
body{
font-family: 'Helvetica', Tahoma, Geneva, Verdana, sans-serif;
}
h1{
color: rgb(119, 214, 124);
}
.site{
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 1em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="cssTest.css">
<title>Twibbon</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.3/fabric.min.js"></script>
<script src="FileSaver.js"></script>
<script src="canvas-toBlob.js"></script>
</head>
<body>
<div class="site">
<h1 class="title">Fortafaste Campaign</h1>
<canvas id="c"></canvas>
<input type="file" id="d" class="button">
<input id="download" type="button" value="download" />
<h2 class="contact">instagram</h2>
</div>
<script>
var canvas = new fabric.Canvas('c');
canvas.setWidth(1080);
canvas.setHeight(1350);
var canvasWrapper = document.getElementById('c');
var canvasWrapperWidth = canvasWrapper.clientWidth;
$(function () {
$(":file").change(function () {
if (this.files && this.files[0]) {
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(this.files[0]);
}
});
});
fabric.Image.fromURL('twibbon2 fortafaste.png',function(img){
img.scaleToWidth(canvas.getWidth());
canvas.setOverlayImage(img, canvas.renderAll.bind(canvas));
});
function imageIsLoaded(e) {
fabric.Image.fromURL(e.target.result,function(img){
var aspectRatio = 1350/1080;
var factor = 1080 / img.width;
img.set({
scaleX: factor,
scaleY: factor
});
canvas.add(img);
canvas.sendToBack(img);
});
};
$("#download").click(function(){
$("#c").get(0).toBlob(function(blob){
saveAs(blob, "myIMG.png");
});
});
</script>
</body>
</html>
I recommend you to simplify your design...
Keep all the information and action buttons on top and the canvas below, here is an example:
.canvas-container canvas {
width: 400px !important;
height: 500px !important;
border: 1px solid blue;
}
body{
font-family: 'Helvetica', Tahoma, Geneva, Verdana, sans-serif;
}
h1{
color: rgb(119, 214, 124);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="cssTest.css">
<title>Twibbon</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.3/fabric.min.js"></script>
<script src="FileSaver.js"></script>
<script src="canvas-toBlob.js"></script>
</head>
<body>
<div class="site">
<div>
<h1 class="title">Fortafaste Campaign</h1>
<input type="file" id="d" class="button">
<input id="download" type="button" value="download" />
<h2 class="contact">instagram</h2>
</div>
<canvas id="c"></canvas>
</div>
<script>
var canvas = new fabric.Canvas('c');
canvas.setWidth(1080);
canvas.setHeight(1350);
var canvasWrapper = document.getElementById('c');
var canvasWrapperWidth = canvasWrapper.clientWidth;
$(function () {
$(":file").change(function () {
if (this.files && this.files[0]) {
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(this.files[0]);
}
});
});
fabric.Image.fromURL('twibbon2 fortafaste.png',function(img){
img.scaleToWidth(canvas.getWidth());
canvas.setOverlayImage(img, canvas.renderAll.bind(canvas));
});
function imageIsLoaded(e) {
fabric.Image.fromURL(e.target.result,function(img){
var aspectRatio = 1350/1080;
var factor = 1080 / img.width;
img.set({
scaleX: factor,
scaleY: factor
});
canvas.add(img);
canvas.sendToBack(img);
});
};
$("#download").click(function(){
$("#c").get(0).toBlob(function(blob){
saveAs(blob, "myIMG.png");
});
});
</script>
</body>
</html>
I'm trying to make a 'draw' app, which allows the user to draw something by dragging their mouse over a canvas.
I want to draw a 'pixel' where the user drags their mouse, however: The location of the mouse and the location where the 'pixels' get drawn are not the same.
I've searched all over the internet but I don't know what the difference is with my version and with theirs.
Image:
HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Drawer</title>
<script src="jquery-2.2.1.min.js"></script>
<script src="scripting/draw.js"></script>
</head>
<body>
<canvas id="drawGround" style="width: 500px; height: 500px; margin: 0 auto; border: 1px solid black;"></canvas>
</body>
</html>
Code:
$(document).ready(function() {
var drawSize = 3;
var canDrawCanvas = false;
const canvasID = "#drawGround";
document.onmouseup = function() {
canDrawCanvas = false;
};
$(canvasID).mousedown(function() {
canDrawCanvas = true;
});
$(canvasID).mousemove(function(event) {
if (canDrawCanvas) handleDrawing(event);
});
function handleDrawing(mouseEvent) {
var canvas = document.getElementById(canvasID.substring(1));
var context = canvas.getContext('2d');
context.fillRect(mouseEvent.pageX, mouseEvent.pageY, drawSize, drawSize);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="drawGround" style="width: 500px; height: 500px; margin: 0 auto; border: 1px solid black;"></canvas>
Instead of scaling the canvas object with the "style" attribute, you should use the "width" and "height"-attributes in the canvas-element.
<canvas id="drawGround" width="500px" height="500px" style="margin: 0 auto; border: 1px solid black;"></canvas>
Then use the offsetX and offsetY parameters instead of pageX and pageY to get the tip position of the mouse:
function handleDrawing(mouseEvent) {
var canvas = document.getElementById(canvasID.substring(1));
var context = canvas.getContext('2d');
context.fillRect(mouseEvent.offsetX, mouseEvent.offsetY, drawSize, drawSize);
}
Is there any methods in KineticJS or in javascript that will allow you to dump object properties and their values.enter code here
All properties that have been set on a Node are in the yourObject.attrs object.
Heres example code:
<!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 circle1 = new Kinetic.Circle({
x:100,
y:100,
radius: 30,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true
});
layer.add(circle1);
layer.draw();
enumerateAttributes(circle1);
function enumerateAttributes(node){
var text="";
var attrs=circle1.getAttrs();
for (key in attrs) {
if (attrs.hasOwnProperty(key)) {
text+=(key+"=="+attrs[key]+"\n");
}
}
alert(text);
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>