How to add a (svg) image to mxGraph - svg

I want to add a image to mxGraph.
At my try I see the frame at the gui and inside the frame is the image text instead of the image.
How can I add a image to mxGraph?
My code looks like that:
const newDiv = document.createElement('div');
const parent = drawIoUi.editor.graph.getDefaultParent();
drawIoUi.editor.graph.getModel().beginUpdate();
const decodetSvg1 = btoa(this._svgTest);
let newChart: any;
try {
newChart = drawIoUi.editor.graph.insertVertex(parent, null, newDiv, 40, 140, 300, 200);
} finally {
const fullImg1 =
`<img alt="" style="width:100%; height:100%;" src="data:image/svg+xml;base64,` +
decodetSvg1 +
`">`;
newChart.setAttribute('label', fullImg1);
drawIoUi.editor.graph.getModel().endUpdate();
drawIoUi.editor.graph.refresh();
drawIoUi.editor.graph.container.focus();
}
And the result looks like that:

Use a shortened data URI in the cell style with an image shape, eg.
graph.insertVertex(parent, null, '', 20, 20, 80, 80,
'shape=image;image=data:image/svg+xml,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIGlkPSJFYmVuZV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDI1MCAyNTAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDI1MCAyNTA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4mI3hhOzxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+JiN4YTsJLnN0MHtmaWxsOiNhMmEyYTI7fSYjeGE7CS5zdDF7ZmlsbDojOGU4ZThlO30mI3hhOwkuc3Qye2ZpbGw6I0ZGRkZGRjt9JiN4YTs8L3N0eWxlPiYjeGE7PHRpdGxlPlplaWNoZW5mbMOkY2hlIDE8L3RpdGxlPiYjeGE7PHBhdGggY2xhc3M9InN0MCIgZD0iTTIzNy41LDIyNy45YzAsNS4zLTQuMyw5LjYtOS41LDkuNmMwLDAsMCwwLDAsMEgyMi4xYy01LjMsMC05LjYtNC4zLTkuNi05LjVjMCwwLDAsMCwwLDBWMjIuMSAgYzAtNS4zLDQuMy05LjYsOS41LTkuNmMwLDAsMCwwLDAsMGgyMDUuOWM1LjMsMCw5LjYsNC4zLDkuNiw5LjVjMCwwLDAsMCwwLDBWMjI3Ljl6Ii8+JiN4YTs8cGF0aCBjbGFzcz0ic3QxIiBkPSJNMjM3LjUsMjI3LjljMCw1LjMtNC4zLDkuNi05LjUsOS42YzAsMCwwLDAsMCwwSDg5LjZMNDQuOCwxOTJsMjcuOS00NS41bDgyLjctMTAyLjdsODIuMSw4NC41VjIyNy45eiIvPiYjeGE7PHBhdGggY2xhc3M9InN0MiIgZD0iTTE5Ny4xLDEzOC4zaC0yMy43bC0yNS00Mi43YzUuNy0xLjIsOS44LTYuMiw5LjctMTJWNTEuNWMwLTYuOC01LjQtMTIuMy0xMi4yLTEyLjNjMCwwLTAuMSwwLTAuMSwwaC00MS43ICBjLTYuOCwwLTEyLjMsNS40LTEyLjMsMTIuMmMwLDAsMCwwLjEsMCwwLjF2MzIuMWMwLDUuOCw0LDEwLjgsOS43LDEybC0yNSw0Mi43SDUyLjljLTYuOCwwLTEyLjMsNS40LTEyLjMsMTIuMmMwLDAsMCwwLjEsMCwwLjEgIHYzMi4xYzAsNi44LDUuNCwxMi4zLDEyLjIsMTIuM2MwLDAsMC4xLDAsMC4xLDBoNDEuN2M2LjgsMCwxMi4zLTUuNCwxMi4zLTEyLjJjMCwwLDAtMC4xLDAtMC4xdi0zMi4xYzAtNi44LTUuNC0xMi4zLTEyLjItMTIuMyAgYzAsMC0wLjEsMC0wLjEsMGgtNGwyNC44LTQyLjRoMTkuM2wyNC45LDQyLjRoLTQuMWMtNi44LDAtMTIuMyw1LjQtMTIuMywxMi4yYzAsMCwwLDAuMSwwLDAuMXYzMi4xYzAsNi44LDUuNCwxMi4zLDEyLjIsMTIuMyAgYzAsMCwwLjEsMCwwLjEsMGg0MS43YzYuOCwwLDEyLjMtNS40LDEyLjMtMTIuMmMwLDAsMC0wLjEsMC0wLjF2LTMyLjFjMC02LjgtNS40LTEyLjMtMTIuMi0xMi4zICBDMTk3LjIsMTM4LjMsMTk3LjIsMTM4LjMsMTk3LjEsMTM4LjN6Ii8+JiN4YTs8L3N2Zz4=;');
You can use this tool to encode the SVG file.

Related

How to install Google Font on nodejs-canvas?

I'm trying to get Google Fonts dynamically with nodejs-canvas and I'm not sure what is the best way to do that.
I understand it needs to be with: "registerFont" method.
This is the code I have now:
const { registerFont, createCanvas, loadImage } = require('canvas')
//registerFont('comicsans.ttf', { family: 'Comic Sans' })
const canvas = createCanvas(200, 200)
const ctx = canvas.getContext('2d')
let name = req.query.name;
// Write "Awesome!"
ctx.font = '30px Impact'
ctx.rotate(0.1)
ctx.fillText(name, 50, 100)
// Draw line under text
var text = ctx.measureText(name)
ctx.strokeStyle = 'rgba(0,0,0,0.5)'
ctx.beginPath()
ctx.lineTo(50, 102)
ctx.lineTo(50 + text.width, 102)
ctx.stroke()
//console.log(canvas.toDataURL());
res.write('<img style="border:1px solid #000;" src="' + canvas.toDataURL() + '" />');
res.end();
Using PT Mono as an example this is how you do it.
First go to the font directly in this case PT Mono.
Next click the "download family" link in the top right. That will give you a zip file which contains the TTF font.
Now copy the ttf file into your node application directory and use registerFont in your file like this.
registerFont('PtMono-Regular.ttf', { family: 'PT Mono' });
As per the documentation make sure you register your fonts before creating the canvas.
Then to use your font on your canvas you'd just use the following to set the font for the context.
ctx.font = "16px 'PT Mono'";
Full Example using our google font just modifying the original example in the node-canvs repo.
const { registerFont, createCanvas } = require('canvas');
registerFont('PtMono-Regular.ttf', { family: 'PT Mono' });
const canvas = createCanvas(500, 500);
const ctx = canvas.getContext('2d');
ctx.font = '16px 'PT Mono'"'
ctx.fillText('This is the font.', 250, 10);

Polygon rendering with pixijs

I'm trying to display more than 6000 Polygons on a mobile device.
Currently, I'm doing this with SVG paths in Android WebView using the d3.js library.
It works but I have to deal with performance issues, my map becomes very laggy when I drag my map or zoom.
My Idea now is to try the same with pixijs. My data comes originally from ESRI Shapefiles. I'm convert these Shapefiles to GeoJSON and then to SVG. My array of vertices looks like this, which I'm trying to pass to the drawPolygon function
0: 994.9867684400124
1: 22.308409862458518
2: 1042.2789743912592
3: 61.07148769269074
But when I try to render these polygon nothing being displayed. This is my code:
var renderer = PIXI.autoDetectRenderer(1800, 1800, { backgroundColor: 0x000000, antialias: true });
document.body.appendChild(renderer.view);
var stage = new PIXI.Container();
var graphics = new PIXI.Graphics();
var totalShapes = feat.features.length;
for (var i = 1; i <= totalShapes -1; i++) {
var shape = feat.features[i];
var geometry = shape.geometry.bbox;
graphics.beginFill(0xe74c3c);
graphics.drawPolygon([ geometry]);
graphics.endFill();
stage.addChild(graphics);
renderer.render(stage);
}
Can someone help me or could suggest me a different way?
I have not seen that way of initializing a pixie project.
Usually you add the application to the html document like:
var app = new PIXI.Application({
width: window.innerWidth,
height: window.innerHeight,
backgroundColor: 0x2c3e50
});
document.body.appendChild(app.view);
If you do this you can add your draw calls to the setup of the application:
app.loader.load(startup);
function startup()
{
var g = new PIXI.Graphics();
g.beginFill(0x5d0015);
g.drawPolygon(
10, 10, 120, 100, 120, 200, 70, 200
);
g.endFill();
app.stage.addChild(g);
}
This will render the polygon once.

Applying clipTo path on image in fabric.js incorrectly repositions the image

Please take a look at this fiddle:
http://jsfiddle.net/2ktvyk4e/5/
var imgUrl, snapshotCanvas;
imgUrl = 'http://cdn-development.wecora.com/boards/backgrounds/000/001/388/cover/ocean-background.jpg';
snapshotCanvas = new fabric.StaticCanvas('snapshotCanvas', {
backgroundColor: '#e0e0e0',
width: 1000,
height: 1500
});
fabric.Image.fromURL(imgUrl, function(img) {
img.set({
width: 1000,
left: 0,
top: 0,
clipTo: function(ctx) {
return ctx.rect(0, 0, 1000, 400);
}
});
return snapshotCanvas.add(img).renderAll();
}, {
crossOrigin: 'Anonymous'
});
It's pretty simple. I'm loading an image and then trying to clip it so that the full width of the canvas but clipped so only the top 400 pixels are showing. For some reason, the clipTo causes the image to move and resize inexplicably:
As you can see, when the clipping path is applied the image is repositioned on the canvas inexplicably. If I remove the clipTo, then the image loads full canvas width no problem (of course its also full height, which we don't want).
I have no idea what is happening here or why this is occuring so any help is appreciated.
Make sure you have originX and originY left to top and left on both the canvas and your image. Also - you don't really need to clip anything to the canvas. The only real use I've found for clipTo was clipping collage images to their bounding shapes. If you want to restrict the image from being dragged above that 400px, I would recommend rendering a rectangle below it (evented = false, selectable = false) and then clipping to that rectangle.
I put this together without clipTo (and changed some numbers so I wasn't scrolling sideways). It renders the image half way down the canvas.
http://jsfiddle.net/2ktvyk4e/6/
Edit:
I dug through some source code to find the clipByName method and the two helper methods for finding stuff. I use this for keeping track of collage images and their bounding rectanlges ("images" and "clips"). I store them in an object:
imageObjects: {
'collage_0': http://some.tld/to/image.ext,
'collage_1': http://some.tld/to/image2.ext
}
Helper methods for finding either the clip or image:
findClipByClipName: function (clipName) {
var clip = _(canvas.getObjects()).where({ clipFor: clipName }).first();
return clip;
},
findImageByClipFor: function (clipFor) {
var image = _(canvas.getObjects()).where({ clipName: clipFor }).first();
return image;
},
Actual clipping method:
clipByName: function (ctx) {
this.setCoords();
var clipRect, scaleXTo1, scaleYTo1;
clipRect = collage.findClipByClipName(this.clipName);
scaleXTo1 = (1 / this.scaleX);
scaleYTo1 = (1 / this.scaleY);
ctx.save();
var ctxLeft, ctxTop;
ctxLeft = -(this.width / 2) + clipRect.strokeWidth;
ctxTop = -(this.height / 2) + clipRect.strokeWidth;
ctx.translate(ctxLeft, ctxTop);
ctx.rotate(degToRad(this.angle * -1));
ctx.scale(scaleXTo1, scaleYTo1);
ctx.beginPath();
ctx.rect(
clipRect.left - this.oCoords.tl.x,
clipRect.top - this.oCoords.tl.y,
clipRect.width,
clipRect.height
);
ctx.closePath();
ctx.restore();
function degToRad(degrees) {
return degrees * (Math.PI / 180);
}
},
And finally adding images to canvas where all of this comes together:
var clipName, clip, image;
clipName = helpers.findKeyByValue(url, this.imageObjects);
clip = this.findClipByClipName(clipName);
image = new Image();
image.onload = function () {
var collageImage = new fabric.Image(image, $.extend({}, collage.commonImageProps, {
left: clip.left,
top: clip.top,
clipName: clipName,
clipTo: function (ctx) {
return _.bind(collage.clipByName, collageImage)(ctx);
}
}));
collage.scaleImagesToClip(collageImage);
canvas.add(collageImage);
};

Can't load SVG from URL

I want to load different shapes in FabricJS based Canvas using loadSVGFromURL(), but can't. Documentation is also not complete on this. I just want a complete example. I can load it from string, but string creates spaces which creates problems when rendering. Here is my code:
var canvas = new fabric.Canvas('canvas');
fabric.loadSVGFromURL('BlueFlower.svg', function (objects) {
var SVG = fabric.util.groupSVGElements(objects, options);
canvas.add(SVG).centerObject(SVG).renderAll();
SVG.setCoords();
});
I have done an example on jsfiddle, that I create two objects and I load an svg image from url, you can take a look.
Here is an example
The snippet for load svg is this:
var site_url = 'http://fabricjs.com/assets/1.svg';
fabric.loadSVGFromURL(site_url, function(objects) {
var group = new fabric.PathGroup(objects, {
left: 165,
top: 100,
width: 295,
height: 211
});
canvas.add(group);
canvas.renderAll();
});

How to preserve spaces in svg text

To preserve spaces in a textelement of svg, one should use 'xml:space="preserve"' as an attribute of the text (jsfiddle). However, it isn't working. What am I doing wrong?
// init snap
var svgElement=document.getElementById("mainSvgId");
var s = Snap(svgElement).attr({height: 300, width: 300});
// greate group with rectanle
var parentGroup=s.g().attr({id: "parent"});
var rect1 = s.rect(0, 0, 200, 200).attr({fill: "#bada55"});
parentGroup.add(rect1);
// add text with preserve attribute
var text = s.text(0, 20, " text1 text2");
text.node.setAttribute("xml:space", "preserve");
parentGroup.add(text);
You're almost there. You need to properly create the attribute in the xml namespace for which you need setAttributeNS rather than setAttribute
text.node.setAttributeNS("http://www.w3.org/XML/1998/namespace", "xml:space", "preserve");

Resources