Exporting chart.js charts to svg using canvas2svg.js - javascript

I am trying to export chart.js chart to svg using canvas2svg.js.
It does not seems to be working, since chart.js refuses to use 'fake' canvas created by canvas2svg.js
My HTML code:
<div style="position: relative; height:20vh; width:100vh">
<canvas id="radarCanvas" ></canvas>
</div>
My script:
var ctx = document.getElementById("radarCanvas").getContext("2d");
var radarChart = new Chart(ctx, graphData); // Works fine
// Create canvas2svg 'fake' context
var c2s = C2S(500,500);
// new chart on 'fake' context fails:
var mySvg = new Chart(c2s, graphData);
// Result (console):
// "Failed to create chart: can't acquire context from the given item"
I've posted full example on Codepen (Sorry for long js there, I could not find a link from which to import canvas2svg so I pasted it at the beginnning of the script.)

If you use a recent Chart.JS version (2.7.1 at time of writing) you can get this running by tweaking canvas2svg a bit.
I added the following code to canvas2svg: Have a look at the Codepen
ctx.prototype.getContext = function (contextId) {
if (contextId=="2d" || contextId=="2D") {
return this;
}
return null;
}
ctx.prototype.style = function () {
return this.__canvas.style
}
ctx.prototype.getAttribute = function (name) {
return this[name];
}
ctx.prototype.addEventListener = function(type, listener, eventListenerOptions) {
console.log("canvas2svg.addEventListener() not implemented.")
}
BUT: It only works if you disable animation and responsiveness of the chart (set to false).

In case somebody stumbles across this question, replacing the ctx in sspechts answer to C2S and disabling animation and responsiveness of the graphdata one can get the svg from the canvas.
I forked the codepen project and added one function which tweaks the library with the codesnippets from sspecht and the two flags:
// deactivate responsiveness and animation
graphData.options.responsive = false;
graphData.options.animation = false;
https://codepen.io/anon/pen/RYVVPY

For devices that have a devicePixelRatio different than 1 or are zoomed in/out I did:
const getDevicePixelRatio = window.devicePixelRatio
window.devicePixelRatio = 1;
// C2S Code
window.devicePixelRatio = getDevicePixelRatio
Otherwise the svg may get cropped.

The most recent version of Chart.js (3.9.1) seems to use setTransform() and resetTransform() methods which are not implemented by Canvas2SVG ( no updates on github for ~5 years ).
This maintained version does implement theses methods : https://github.com/zenozeng/svgcanvas/ ( https://www.npmjs.com/package/svgcanvas ).
However, it seems to have issues for drawing line. I wrote a little workaround for that ( see https://github.com/zenozeng/svgcanvas/issues/25 ).
I hope it'll help.

Related

Get the pixel screen size in Spark AR studio (for Facebook)

I am starting to work with Spark AR studio and I looking for to get the screen size in pixel to compare the coordinate obtained by the gesture.location on Tap.
TouchGestures.onTap().subscribe((gesture) => {
// ! The location is always specified in the screen coordinates
Diagnostics.log(`Screen touch in pixel = { x:${gesture.location.x}, y: ${gesture.location.y} }`);
// ????
});
The gesture.location is in pixel (screen coordinate) and would like to compare it with the screen size to determine which side of the screen is touched.
Maybe using the Camera.focalPlane could be a good idea...
Update
I tried two new things to have the screen size:
const CameraInfo = require('CameraInfo');
Diagnostics.log(CameraInfo.previewSize.height.pinLastValue());
const focalPlane = Scene.root.find('Camera').focalPlane;
Diagnostics.log(focalPlane.height.pinLastValue());
But both return 0
This answer might be a bit late but it might be a nice addition for people looking for a solution where the values can easily be used in script, I came across this code(not mine, forgot to save a link):
var screen_height = 0;
Scene.root.find('screenCanvas').bounds.height.monitor({fireOnInitialValue: true}).subscribe(function (height) {
screen_height = height.newValue;
});
var screen_width = 0;
Scene.root.find('screenCanvas').bounds.width.monitor({fireOnInitialValue: true}).subscribe(function (width) {
screen_width = width.newValue;
});
This worked well for me since I couldn't figure out how to use Diagnostics.log with the data instead of Diagnostics.watch.
Finally,
Using the Device Info in the Patch Editor and passing these to the script works!
First, add a variable "to script" in the editor:
Then, create that in patch editor:
And you can grab that with this script:
const Patches = require('Patches');
const screenSize = Patches.getPoint2DValue('screenSize');
My mistake was to use Diagnostic.log() to check if my variable worked well.
Instead use Diagnostic.watch():
Diagnostic.watch('screenSize.x', screenSize.x);
Diagnostic.watch('screenSize.y', screenSize.y);
Screen size is available via the Device Info patch output, after dragging it to patch editor from the Scene section.
Now in the open beta (as of this post) you can drag Device from the scene sidebar into the patch editor to get a patch that outputs screen size, screen scale, and safe area inserts as well as the self Object.
The Device patch
The device size can be used in scripts using CameraInfo.previewSize.width and CameraInfo.previewSize.height respectively. For instance, if you wanted to get 2d points representing the min/max points on the screen, this'd do the trick.
const CameraInfo = require('CameraInfo')
const Reactive = require('Reactive')
const min = Reactive.point2d(
Reactive.val(0),
Reactive.val(0)
)
const max = Reactive.point2d(
CameraInfo.previewSize.width,
CameraInfo.previewSize.height
)
(The point I want to emphasize being that CameraInfo.previewSize.width and CameraInfo.previewSize.height are ScalarSignals, not number literals.)
Edit: Here's a link to the documentation: https://sparkar.facebook.com/ar-studio/learn/documentation/reference/classes/camerainfomodule

Highchart 3D Pie Chart Label color?

I'm trying to use a dark background for my HighChart 3D Pie Chart. By default, the text is black with white glow.
My goal is to have something similar to:
https://www.highcharts.com/demo/pie-gradient/dark-unica
I'm using the WordPress plugin wpdatatables to create the actual pie and was given the following support:
"You can check in our documentation about wpDataCharts callbacks. Every chart exposes a number of options that customize its look and feel. Charts usually support custom options appropriate to that visualization. This callbacks allows adding options that are available in Google Charts API, Highcharts API and Chart.js API"
https://wpdatatables.com/documentation/information-for-developers/wpdatacharts-callbacks/
I tried the following code based on support and HighChart website
jQuery(window).load(function() {
if (typeof wpDataChartsCallbacks == 'undefined') {
wpDataChartsCallbacks = {};
}
wpDataChartsCallbacks[14] = function(obj) {
obj.options.plotOptions.series.dataLabels.color = '#FF0000';
obj.options.chart.backgroundColor = '#GG0000';
obj.options.chart.zoomType = 'x';
obj.options.chart.panning = true;
obj.options.chart.panKey = 'shift';
obj.options.tooltip = {
formatter: function() {
var s = '<b>$' + this.y + '</b>';
return s;
}
}
}
});
I added that line:
obj.options.plotOptions.series.dataLabels.color = '#FF0000';
but doesn't seems to be working.
Any help would be appreciated. Thanks.
I've never used Wordpress callbacks as you are doing, but whenever I need to update a chart's options, I've found that you need to refer to the series as an array, even if you have only one in your chart.
Try this and see whether it works:
obj.options.plotOptions.series[0].dataLabels.color = '#FF0000';
Update: Please see the comment from #ppotaczek below for the correct syntax.

Adjusting Canvas size to image size with Pixi.js

I'm working on a really basic image editor (designed primarily to place text on an image), using PixiJS... though this may be more of a Canvas question, I'm not sure how to classify it as I'm green to Canvas and completely new to Pixi. Unfortunately I can't replicate the behavior in JSFiddle. As of now, I only have this running on localhost, but if anyone has suggestions on how to share this code, I'm open for any feedback.
The idea is that users would be able to select a image to edit (templates for various forms of signage), with the canvas rendering to the size of the image and adding said image as a child on loading the page. For now I'm using a 400 x 650px placeholder for testing purposes. The problem is that on an initial loading or hard refresh of the page, the canvas size defaults to Pixi's 800 x 600px. Soft refreshing the page will size the canvas to the image's dimensions, but I'd like to fix this issue... and I'm sure it's probably an easy fix, but I'm in uncharted waters here. Any help is appreciated. Thanks in advance.
I apologize if some of this code looks wonky, I'm fully aware this is a huge mess right now.
Javascript (this is actually in an AngularJS controller for the time being)
var img = new Image();
var signagetemplate = "placeholderSIGN.png";
img.src = signagetemplate;
var canwidth = img.width;
var canheight = img.height;
var renderer = PIXI.autoDetectRenderer(canwidth, canheight, {
transparent: true,
resolution: 1
});
document.getElementById('display').appendChild(renderer.view);
var stage = new PIXI.Container();
PIXI.loader
.add("signitem", signagetemplate)
.load(setup);
function setup() {
signitem = new PIXI.Sprite(
PIXI.loader.resources["signitem"].texture
);
stage.addChild(signitem);
renderer.render(stage);
}
Edit 9/21/17
I've tried using Pixi's built-in loader as suggested by Hachi in the comments to load the image, but it doesn't seem to load it at all. In the log, it's undefined. I don't understand this loader...
loader.add('signitem', signagetemplate);
loader.load((loader, resources) => {
console.log(resources.name, 'loaded.', 'progress:',resources.progressChunk, '%');
});
loader.load(setup);
I figured it out. All of the examples I found for working with the loader confused me a little bit, mainly just the syntax for entering basic JavaScript. Whether or not this is the cleanest way of going about the problem, I'm not sure, but this seems to work, at least locally. My feelings will not be hurt if someone comes along with a better solution.
var container = new PIXI.Container();
var signagetemplate = //Image to be loaded
var loader = PIXI.loader;
var canwidth;
var canheight;
var renderer = PIXI.autoDetectRenderer({
transparent: true,
resolution: 1
});
loader.add("signtemp", signagetemplate)
loader.on('complete', function(loader, resources, IMAGE) {
var signitem = new PIXI.Sprite(loader.resources.signtemp.texture);
canwidth = signitem.width;
canheight = signitem.height;
container.addChild(signitem);
})
loader.load(setup);
function setup() {
renderer.resize(canwidth, canheight);
renderer.render(container);
}
document.getElementById('display').appendChild(renderer.view);

Create js animation of a horizontal spritesheet

I have gone through the docs and sample only to be lost in outdated docs. Apparently there is no samples for the latest version of createjs.
I need to smooth scroll a horizontal spritesheet. So that the middle of images are shown before the new image is entirely in the "window". So the place in the page doesnt move only what is displayed from the single column horizontal spritesheet is different. And we do not switch between images we scroll up and down.
I am at my wits end with this.
this.sprite = new createjs.BitmapAnimation(spriteSheet);
that line gives an error
not a constructor
this.sprite = createjs.BitmapAnimation(spriteSheet);
gives an error
not a function
here is the sprite sheet
https://github.com/nydehi/asp.net-mvc-example-invoicing-app/blob/master/screenshots/1.png
i am doing this now and no error but nothing is displayed.
<script type="text/javascript" src="createjs-2014.12.12.min.js"></script>
<script>
function init() {
var data = {
images: ["1.png"],
frames: {width:15, height:20},
animations: {
stand:0,
run:[1,5],
jump:[6,8,"run"]
}
};
var spriteSheet = new createjs.SpriteSheet(data);
var animation = new createjs.Sprite(spriteSheet, "run");
var stage = new createjs.Stage("demoCanvas");
stage.addChild(animation);
animation.gotoAndPlay("run"); //walking from left to right
stage.update();
}
</script>
You're probably using a more recent version of CreateJS (around version 0.8.2) which no longer has a BitmapAnimation class on it.
Older versions (0.6.0) had it, but it was most likely replaced by the SpriteSheet class.
Check here for the most recent documentation.
The earlier comments about BitmapAnimation being deprecated long ago are right. Your updated code sample looks fine otherwise.
I think you are just missing something to update the stage when contents change. Your sample just has the one update, but because your image is loaded using a string path, it is not ready yet when you call stage.update().
Any time contents change, you need to tell the stage to refresh. Typically, this is manually controlled when contents change, or constantly using the Ticker.
createjs.Ticker.on("tick", function(event) {
// Other updates
// Update the stage
stage.update(event);
});
// Or a handy shortcut if you don't need to do anything else on tick:
createjs.Ticker.on("tick", stage);

Sketch Plugin: How to programmatically make a layer exportable?

So, in Sketch, you can mark a layer/group as exportable.
And then the layer/group can be exported as .png/.svg/.pdf etc. I was trying to make a Sketch Plugin recently, where I need to mark a layer/group as exportable from code. A layer in code is represented using MSLayer and group is MSLayerGroup. The sketch documentation is not mature enough yet, so I used ClassDump to extract all the headers that has been used in the app. I have been looking for a method that might seem to do my job, but it has been days and am still out of luck. Can anybody please help me out in this regard?
Sketch supports slice and export to image. You can use - (void)saveArtboardOrSlice:(id)arg1 toFile:(id)arg2;
method of MSDocument.
This is almost how to do it.
var loopLayerChildren = [[layerToExport children] objectEnumerator],
rect = [MSSliceTrimming trimmedRectForSlice:layer],
useSliceLayer = false,
exportFilePath,
slice;
// Check for MSSliceLayer and overwrite the rect if present
while (layerChild = [loopLayerChildren nextObject]) {
if ([layerChild class] == 'MSSliceLayer') {
rect = [MSSliceTrimming trimmedRectForSlice:layerChild];
useSliceLayer = true;
}
}
slice = [MSExportRequest requestWithRect:rect scale:1];
if (!useSliceLayer) {
slice.shouldTrim = true;
}
// export to image file
[(this.document) saveArtboardOrSlice: slice toFile:exportFilePath];
Reference from #GeertWill's sketch-to-xcode-assets-catalog plugin.

Categories