The code shown below is from this post. It works fine when using fabric.js/1.4.0, but when I update fabric.js to 2.4.3, it fails to run. The issue is that the clipTo funtion has been replaced by a new function called clipPath. Does anyone know how to update this code so it works with clipPath? I've gone through the docs for clipPath and have been searching Google and Stackoverflow for almost 2 days, but I'm still lost.
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
img.onload = function() {
var OwnCanv = new fabric.Canvas('c', {
isDrawingMode: true
});
var imgInstance = new fabric.Image(img, {
left: 0,
top: 0,
});
OwnCanv.add(imgInstance);
OwnCanv.freeDrawingBrush.color = "purple"
OwnCanv.freeDrawingBrush.width = 4
OwnCanv.on('path:created', function(options) {
var path = options.path;
OwnCanv.isDrawingMode = false;
OwnCanv.remove(imgInstance);
OwnCanv.remove(path);
OwnCanv.clipTo = function(ctx) {
path.render(ctx);
};
OwnCanv.add(imgInstance);
});
}
img.src = "http://upload.wikimedia.org/wikipedia/commons/3/33/Jbassette4.jpg?uselang=fi";
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>
Ok, so the path, right after being created is already cached.
What you need to do is set the fill to a color that is not null, using the 'set' method.
Then set the path as clipPath for the canvas, or the Object itself.
If you want to set it just for the object, you need to recalculate its correct position.
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
img.onload = function() {
var OwnCanv = new fabric.Canvas('c', {
isDrawingMode: true
});
var imgInstance = new fabric.Image(img, {
left: 0,
top: 0,
});
OwnCanv.add(imgInstance);
OwnCanv.controlsAboveOverlay = true;
OwnCanv.freeDrawingBrush.color = "purple"
OwnCanv.freeDrawingBrush.width = 4
OwnCanv.on('path:created', function(options) {
var path = options.path;
path.set('fill', 'black');
console.log(path)
OwnCanv.isDrawingMode = false;
OwnCanv.remove(path);
OwnCanv.clipPath = path;
});
}
img.src = "http://upload.wikimedia.org/wikipedia/commons/3/33/Jbassette4.jpg?uselang=fi";
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>
You need to have objectCaching on false on the path.
Check here:https://jsfiddle.net/jw6rLx5f/2/
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
img.onload = function() {
var OwnCanv = new fabric.Canvas('c', {
isDrawingMode: true
});
var imgInstance = new fabric.Image(img, {
left: 0,
top: 0,
});
OwnCanv.add(imgInstance);
OwnCanv.freeDrawingBrush.color = "purple"
OwnCanv.freeDrawingBrush.width = 4
OwnCanv.on('path:created', function(options) {
var path = options.path;
path.objectCaching= false;
OwnCanv.isDrawingMode = false;
OwnCanv.remove(imgInstance);
OwnCanv.remove(path);
OwnCanv.clipTo = function(ctx) {
ctx.save();
path.render(ctx);
ctx.restore();
};
OwnCanv.add(imgInstance);
});
}
img.src = "http://upload.wikimedia.org/wikipedia/commons/3/33/Jbassette4.jpg?uselang=fi";
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.js"></script>
<canvas id="c" width="500" height="500"></canvas>
Related
Im trying to make drawing app where you can draw something on canvas and save your result as an image on the server by clicking "save" button. You can also put another image as background for your drawing. The problem is that when I put an image to the canvas using ctx.drawImage() I can't save the canvas as an image because nothing happens. Everything works ok until I use ctx.drawImage(). Why I can't save canvas as an image with another image in it?
My ajax code:
// it works until I use ctx.drawImage()
$.ajax({
type: "POST",
url: "save.php",
data: {image: dataURL},
success: function()
{
alert('saved');
}
});
Code for putting another image as background:
//var ctx = can.getContext('2d');
var img = new Image;
ctx.drawImage (img, 0, 0);
My PHP code:
<?php
$dataURL = $_POST["image"];
$parts = explode(',', $dataURL);
$data = $parts[1];
$data = base64_decode($data);
$fp = fopen('test.png', 'w');
fwrite($fp, $data);
fclose($fp);
?>
This is the entire javascript code
$(document).ready (function()
{
var color = $("#color").val();
$("#size").val("10");
var mouse = 0;
var can = document.getElementById("canny");
var ctx = can.getContext('2d');
var offsetX = 158;
var offsetY = 200;
var img = new Image;
var url = "http://i.imgur.com/fmAoxZ0.jpg";
img.src = url;
function setBackground()
{
ctx.drawImage (img, 0, 0);
}
function setOpacity(newValue)
{
$("#canny").css ("opacity", newValue * 0.01);
$("#txt-opacity").html(newValue + "%");
}
$("body").mousedown(function(event)
{
color = $("#color").val();
var cordX = event.clientX - offsetX;
var cordY = event.clientY - offsetY;
var size = $("#size").val();
ctx.beginPath();
ctx.arc(cordX,cordY,size,0,2*Math.PI);
ctx.fillStyle = color;
ctx.fill();
document.getElementById("coords").innerHTML = "x: " + cordX + " y: " + cordY;
mouse = 1;
$("body").mousemove(function(event)
{
if (mouse == 1)
{
var cordX = event.clientX - offsetX;
var cordY = event.clientY - offsetY;
var size = $("#size").val();
ctx.beginPath();
ctx.arc(cordX,cordY,size,0,2*Math.PI);
ctx.fillStyle = color;
ctx.fill();
$("body").mouseup(function()
{
mouse = 0;
});
}
});
mouse = 1;
});
$("#opacity").change (function()
{
setOpacity(this.value);
});
$("#opacity").trigger("change");
$("#red").click (function()
{
$("#color").val("#FF3636");
$(this).css ("border-color", "darkorange");
$("#blue").css ("border-color", "black");
$("#lime").css ("border-color", "black");
$("#yellow").css ("border-color", "black");
});
$("#blue").click (function()
{
$("#color").val("#0080FF");
$(this).css ("border-color", "darkorange");
$("#red").css ("border-color", "black");
$("#lime").css ("border-color", "black");
$("#yellow").css ("border-color", "black");
});
$("#lime").click (function()
{
$("#color").val("#8CFF00");
$(this).css ("border-color", "darkorange");
$("#red").css ("border-color", "black");
$("#blue").css ("border-color", "black");
$("#yellow").css ("border-color", "black");
});
$("#yellow").click (function()
{
$("#color").val("#FFF01F");
$(this).css ("border-color", "darkorange");
$("#red").css ("border-color", "black");
$("#blue").css ("border-color", "black");
$("#lime").css ("border-color", "black");
});
$("#btn-clear").click(function()
{
if (confirm ("Are you sure to clear your image?"))
{
ctx.clearRect(0, 0, can.width, can.height);
}
});
$("#btn-save").click (function()
{
var dataURL = can.toDataURL();
$.ajax({
type: "POST",
url: "save.php",
data: {image: dataURL},
success: function()
{
alert('saved');
}
});
});
$("#fill").click (function()
{
$("#canny").css ("background-color", color);
});
$('input[type=radio][name=bgselect]').change (function ()
{
if (this.value == "image")
{
setBackground();
$("#url").css ("visibility", "visible");
img.src = url;
} else
{
$('#canny').css('background-image', 'none');
$("#url").css ("visibility", "hidden");
}
});
$("#url").change(function()
{
url = $(this).val();
setBackground();
});
});
Your problem is be with canvas.toDataURL which is disabled if you draw cross-domain images to your canvas. If you open your browser console using F12 you will see the security error.
Since you're image host (imgur.com) has enabled cross-domain access to your image, you can comply with cross-domain security by adding img.crossOrigin='anonymous' to your img object.
var img = new Image;
img.crossOrigin='anonymous';
var url = "http://i.imgur.com/fmAoxZ0.jpg";
img.src = url;
I'm looking for a clean way to convert a SVG to PNG and download, in Vue 2. What is the best approach ?
I finally managed to come up with this solution:
save() {
const a = document.querySelector("a");
const triggerDownload = (imgURI: string) => {
const evt = new MouseEvent("click", {
view: window,
bubbles: false,
cancelable: true,
});
a?.setAttribute("download", "FileName.png");
a?.setAttribute("href", imgURI);
a?.setAttribute("target", "_blank");
a?.dispatchEvent(evt);
};
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
const ctx = canvas.getContext("2d");
data = new XMLSerializer().serializeToString(
document.getElementById("svgId") as Node
);
const DOMURL = window.URL || window.webkitURL || window;
const img = new Image();
const svgBlob = new Blob([data], { type: "image/svg+xml;charset=utf-8" });
const url = DOMURL.createObjectURL(svgBlob);
img.onload = function () {
ctx?.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
const imgURI = canvas
.toDataURL("image/png")
.replace("image/png", "image/octet-stream");
triggerDownload(imgURI);
ctx?.clearRect(0, 0, canvas.width, canvas.height);
};
img.src = url;
},
I am trying to write on image with hindi language. I am using node-canvas library. There is some problem with my output. Can someone help me ?
const { createCanvas, loadImage, registerFont} = require('canvas')
const canvas = createCanvas(400, 400)
const ctx = canvas.getContext('2d')
var str= "यह. मिसिसिपी है";
console.log(str);
loadImage('missisippi.jpg').then((image) => {
console.log(image);
ctx.drawImage(image, 0 , 0, 400, 400);
ctx.fillText(str,100,40);
var body = canvas.toDataURL(),
base64Data = body.replace(/^data:image\/png;base64,/,""),
binaryData = new Buffer(base64Data, 'base64').toString('binary');
require("fs").writeFile("out.png", binaryData, "binary", function(err) {
console.log(err); // writes out file without error, but it's not a valid image
})
// console.log('<img src="' + canvas.toDataURL() + '" />')
})
This is the output image . You can see that मिसिसिपी is grammatically wrong. (In case u are familiar with Hindi.
I have also tried the very same thing with npm-gm. in that too I faced same issue. Can someone help me out in this issue ?
How can I write text on image with custom font ?
The following is working fine for me -
var fs = require('fs')
var path = require('path')
var Canvas = require('canvas')
function fontFile (name) {
return path.join(__dirname, '/fonts/', name)
}
Canvas.registerFont(fontFile('ARBLI___0.ttf'), {family: 'ARBLI___0'})
var canvas = Canvas.createCanvas(7100, 3500)
var ctx = canvas.getContext('2d')
var Image = Canvas.Image;
var img = new Image();
img.src = 'input/DOIT_Art_Size.jpg';
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.font = '150pt ARBLI___0'
ctx.fillText('यह मिसिसिपी है',3900, 1700)
canvas.createPNGStream().pipe(fs.createWriteStream(path.join(__dirname, 'output/font.png')))
canvas.createJPEGStream().pipe(fs.createWriteStream(path.join(__dirname, 'output/font.jpg')))
My node version is 6.11.2.
Canvas module is 2.0.0-alpha.16.
My input image dimension is 7100*3500 pixels.
I use pixi.js v 3.0.0
My simple code is
(function () {
document.addEventListener('DOMContentLoaded', function () {
var width = screen.availWidth;
var height = screen.availHeight;
var renderer = PIXI.CanvasRenderer(width, height, {
backgroundColor : 0x1099bb
});
document.body.appendChild(renderer.view);
var stage = new PIXI.Container();
var texture = PIXI.Texture.fromImage('asset/bunny.png');
var bunny = new PIXI.Sprite(texture);
bunny.anchor.x = 0.5;
bunny.anchor.y = 0.5;
bunny.position.x = 200;
bunny.position.y = 150;
stage.addChild(bunny);
animate();
function animate() {
requestAnimationFrame(animate);
bunny.rotation += 0.1;
renderer.render(stage);
}
}, false);
}
());
But i get: TypeError: this.initPlugins is not a function if use CanvasRenderer but it works in other cases
Just add new keyword when creating the CanvasRenderer.
How do I create rectangles with 4 ports (each side) in a correct way, so I can save and restore them via JSON?
I tried this one, but only the rectangles are been saved. The connections and labels got lost.
JSFiddle: http://jsfiddle.net/xfvf4/36/
Create two elements (Add) - move them and connect them
Write: This gives the content as JSON-Array
Read: Should make the grafic out of the JSON-Array
The last point doesn't work.
JS:
var LabelRectangle = draw2d.shape.basic.Rectangle.extend({
NAME: "draw2d.shape.basic.Rectangle",
init: function (attr) {
this._super(attr);
this.label = new draw2d.shape.basic.Label({
text: "Text",
fontColor: "#0d0d0d",
stroke: 0
});
this.add(this.label, new draw2d.layout.locator.CenterLocator(this));
this.label.installEditor(new draw2d.ui.LabelInplaceEditor());
this.createPort("hybrid", new draw2d.layout.locator.BottomLocator(this));
},
getPersistentAttributes: function () {
var memento = this._super();
memento.labels = [];
var ports = [];
ports = this.getPorts();
memento.ports = [];
console.log(ports);
this.children.each(function (i, e) {
console.log(e);
memento.labels.push({
id: e.figure.getId(),
label: e.figure.getText(),
locator: e.locator.NAME
});
ports.each(function (i, e) {
memento.ports.push({
//id: e.id,
name: e.name,
locator: e.locator.NAME
});
});
});
return memento;
},
setPersistentAttributes: function (memento) {
this._super(memento);
this.resetChildren();
$.each(memento.labels, $.proxy(function (i, e) {
var label = new draw2d.shape.basic.Label(e.label);
var locator = eval("new " + e.locator + "()");
locator.setParent(this);
this.add(label, locator);
}, this));
}
});
$(window).load(function () {
var canvas = new draw2d.Canvas("gfx_holder");
$("#add").click(function (e) { // Add a new rectangle
var rect = new LabelRectangle({
width: 200,
height: 40,
radius: 3,
bgColor: '#ffffff',
stroke: 0
});
rect.createPort("hybrid", new draw2d.layout.locator.OutputPortLocator(rect));
rect.createPort("hybrid", new draw2d.layout.locator.InputPortLocator(rect));
rect.createPort("hybrid", new draw2d.layout.locator.TopLocator(rect));
canvas.add(rect, 150, 200);
});
$("#write").click(function (e) { // Write to pre-Element (JSON)
var writer = new draw2d.io.json.Writer();
writer.marshal(canvas, function(json){
$("#json").text(JSON.stringify(json,null,2));
$('#gfx_holder').empty();
});
});
$("#read").click(function (e) { // Read from pre-Element (JSON)
var canvas = new draw2d.Canvas("gfx_holder");
var jsonDocument = $('#json').text();
var reader = new draw2d.io.json.Reader();
reader.unmarshal(canvas, jsonDocument);
});
});
HTML:
<ul class="toolbar">
<li>Add</li>
<li>Write</li>
<li>Read</li>
</ul>
<div id="container" class="boxed">
<div onselectstart="javascript:/*IE8 hack*/return false" id="gfx_holder" style="width:100%; height:100%; ">
</div>
<pre id="json" style="overflow:auto;position:absolute; top:10px; right:10px; width:350; height:500;background:white;border:1px solid gray">
</pre>
</div>
Just use the write.js and Reader.js in the "json"-Folder of Draw2D.js 5.0.4 and this code:
$(window).load(function () {
var canvas = new draw2d.Canvas("gfx_holder");
// unmarshal the JSON document into the canvas
// (load)
var reader = new draw2d.io.json.Reader();
reader.unmarshal(canvas, jsonDocument);
// display the JSON document in the preview DIV
//
displayJSON(canvas);
// add an event listener to the Canvas for change notifications.
// We just dump the current canvas document into the DIV
//
canvas.getCommandStack().addEventListener(function(e){
if(e.isPostChangeEvent()){
displayJSON(canvas);
}
});
});
function displayJSON(canvas){
var writer = new draw2d.io.json.Writer();
writer.marshal(canvas,function(json){
$("#json").text(JSON.stringify(json, null, 2));
});
}
This should work:
var LabelRectangle = draw2d.shape.basic.Rectangle.extend({
NAME: "draw2d.shape.basic.Rectangle",
init: function (attr) {
this._super(attr);
this.label = new draw2d.shape.basic.Label({
text: "Text",
fontColor: "#0d0d0d",
stroke: 0
});
this.add(this.label, new draw2d.layout.locator.CenterLocator(this));
this.label.installEditor(new draw2d.ui.LabelInplaceEditor());
},
getPersistentAttributes: function () {
var memento = this._super();
memento.labels = [];
memento.ports = [];
this.getPorts().each(function(i,port){
memento.ports.push({
name : port.getName(),
port : port.NAME,
locator: port.getLocator().NAME
});
});
this.children.each(function (i, e) {
memento.labels.push({
id: e.figure.getId(),
label: e.figure.getText(),
locator: e.locator.NAME
});
});
return memento;
},
setPersistentAttributes: function (memento) {
this._super(memento);
this.resetChildren();
if(typeof memento.ports !=="undefined"){
this.resetPorts();
$.each(memento.ports, $.proxy(function(i,e){
var port = eval("new "+e.port+"()");
var locator = eval("new "+e.locator+"()");
this.add(port, locator);
port.setName(e.name);
},this));
}
$.each(memento.labels, $.proxy(function (i, e) {
var label = new draw2d.shape.basic.Label(e.label);
var locator = eval("new " + e.locator + "()");
locator.setParent(this);
this.add(label, locator);
}, this));
}
});