Sketch Plugin: How to programmatically make a layer exportable? - javascript

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.

Related

Does have instagram masks specified UI to chage the 3d objects instead changing textures only?

So i have 3 different, which contains different 3d objects with special animations.
First is 3d objects rotating above the head and change the angle of orbit with our head shakes. The second one is falling 2d sprites all around character calling by eye closing. And the third one is simple facemesh with grid texture on it. Im draw special UI and code it, so in ArPlayer it works perfects, but when im try to upload it to facebook this UI not working and i have only mask number 1.
So im try to search the solution on Youtube and have only this, but this works only with texture changing i think. So my question is: Can i use instagram changing ui with my effects and if yes, how i can do this. Thaks a lot!
P.S: All images u can find.
Effects must not use custom buttons, keyboards, pickers or sliders - effects may use the native UI picker and slider only. (Spark AR Review Policies 2.6)
Using the Native UI picker, you can not only change textures, but also the visibility of objects.
Example:
Create a new project
Create several plane objects on the scene (for example 3 pieces) and name them obj0,
obj1, obj2 and make them invisible
In Capabilities add Native UI -> Picker
Add 3 textures to the project and name them icon_1, icon_2, icon_3 and check the "No compression" option for everyone
Add such a script
const NativeUI = require('NativeUI');
const Textures = require('Textures');
const Scene = require('Scene');
Promise.all([
Textures.findFirst('icon_1'),
Textures.findFirst('icon_2'),
Textures.findFirst('icon_3'),
Scene.root.findFirst('obj0'),
Scene.root.findFirst('obj1'),
Scene.root.findFirst('obj2')
]).then(onReady);
function onReady(assets) {
const texture0 = assets[0];
const texture1 = assets[1];
const texture2 = assets[2];
const objects = [assets[3],assets[4],assets[5]];
const picker = NativeUI.picker;
const index = 0;
const configuration = {
selectedIndex: index,
items: [
{image_texture: texture0},
{image_texture: texture1},
{image_texture: texture2}
]
};
picker.configure(configuration);
picker.visible = true;
picker.selectedIndex.monitor({fireOnInitialValue:true}).subscribe(function(index) {
objects[index.newValue].hidden = false;
if(index.oldValue != undefined)
{
objects[index.oldValue].hidden = true;
}
});
}
A similar official example is from developers, there they used Native UI picker (script) + patch to hide objects. Launch Spark AR Studio and create new project from template "3D Stickers" and watch how they did it. If you don’t have such a project template, update Spark AR Studio.

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.

Exporting chart.js charts to svg using canvas2svg.js

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.

P5js SVG Export

I have a P5js sketch which creates a font that users can type anything they want.
I want to allow the user to download an svg/pdf (vector) version of their result.
As of now I succeeded to have them download a .jpg version using the save order and saving a shot of my screen.
Any ideas?
That's an old thread, but maybe my solution will be useful to someone. To export vector graphics in P5js to SVG file, first I use SVG renderer from p5.svg.js library - this will put svg element directly into HTML document. Exporting is to extract the content of that element (by outerHTML property) and save it to a file (like in this post).
So, for example, your "Save as SVG" button callback function may look like this:
function downloadSvg()
{
let svgElement = document.getElementsByTagName('svg')[0];
let svg = svgElement.outerHTML;
let file = new Blob([svg], { type: 'plain/text' });
let a = document.createElement("a"), url = URL.createObjectURL(file);
a.href = url;
a.download = 'exported.svg';
document.body.appendChild(a);
a.click();
setTimeout(function()
{
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
From googling "p5.js svg", there doesn't seem to be a built-in way to work with SVG images in p5.js.
However, that search returns several promising results:
Here is a GitHub issue with a discussion about working with SVGs in p5.js.
Here is a project that attempts to add SVG support to p5.js:
The main goal of p5.SVG is to provide a SVG runtime for p5.js, so that we can draw using p5's powerful API in <svg>, save things to svg file and manipulating existing SVG file without rasterization.
Another discussion that links to two more SVG libraries.
The p5.SVG library sounds especially promising. I suggest you try something out and post an MCVE if you get stuck.
A new package called canvas-sketch seems to solve this issue. They have a wealth of examples for p5.js as well.
const canvasSketch = require('canvas-sketch')
const p5 = require('p5')
const settings = {
p5: { p5 },
// Turn on a render loop
animate: true,
}
canvasSketch(() => {
// Return a renderer, which is like p5.js 'draw' function
return ({ p5, time, width, height }) => {
// Draw with p5.js things
p5.background(0)
p5.fill(255)
p5.noStroke()
const anim = p5.sin(time - p5.PI / 2) * 0.5 + 0.5
p5.rect(0, 0, width * anim, height)
};
}, settings)
If you use p5 globally, there's also an example for that called animated-p5.js

Is it possible to extend a class that already inherits from another class?

I know the direct answer is no here but I've spoken with a couple people who seem to think it's possible. Here is my code:
var Tile = function(xPos, yPos, state) {
this.createTile(xPos, yPos, state);
}
Tile.prototype = new createjs.Shape();
Tile.prototype.createTile = function(xPos, yPos, state) {
// debugger;
this.x = xPos;
this.y = yPos;
this.onState = state;
var fillCommand = this.graphics.beginFill("#969696").command;
var shapeCommand = this.graphics.drawRoundRect(0, 0, 50, 50, 10).command;
this.on("click", function(){this.toggleState(fillCommand);});
stage.addChild(this);
stage.update();
}
Tile.prototype.toggleState = function(fillCommand) {
if (this.onState === true) {
fillCommand.style = "#969696";
stage.update();
this.onState = false;
} else if (this.onState === false) {
fillCommand.style = "#000000";
stage.update();
this.onState = true;
}
}
Shape() is implemented in easeljs if anyone is familiar with it. Basically here I'm creating a Tile class to represent little rounded squares that will change color when they're pressed. Syntax-wise I get no errors nothing displays on the web page. I already have the correct code to call Tile and the canvas already set up or I'd put that code here too. What I'm asking here is, do I have the right idea in this implementation?
Its a little unconventional but if it works for you then more power to you. The more common way to inherit from Shape would be doing something like
Tile.prototype = Object.create(createjs.Shape.prototype);
Tile.prototype.constructor = Tile;
Inheritance in Javascript is a little strange so, unless you have the time and energy to go down a deep rabbit hole, I would recommend just sticking with what's working. If you do feel like reading more this is a great article to get you started: http://ejohn.org/blog/simple-javascript-inheritance/
EaselJS contributor here - you can absolutely extend EaselJS classes. There is actually a tutorial on the EaselJS site for it. As other people have mentioned, JavaScript inheritance is kind of a pain, and not necessarily the best approach (for example, I always compose shapes/sprites instead of inheriting from them. But it is totally possible, just look at the EaselJS hierarchy: EventDispatcher > DisplayObject > Bitmap.
With your example, you should probably use the approach in the tutorial, where you override initialize, and ensure the superclasses version is called. Its a little dirty, but used extensively until EaselJS 0.7.1 (the latest release).
The New Way
Even better though, the latest version of CreateJS (only available in GitHub as the NEXT version, which should be tagged and published to the CDN soon!) has a brand new model for inheritance that is even easier, and does things like automatically injecting super methods, including the ability to call the super constructor.
function MyClass(arg) {
this.EventDispatcher_constructor();
this.doSomethingWith(arg);
}
var p = createjs.extend(MyClass, createjs.EventDispatcher);
// Add new methods
p.doSomethingWith = function() {
// whatever
}
// Override methods
p.addEventListener = function(name, listener) {
this.EventDispatcher_addEventListener(name, listener);
// custom stuff here
}
// Promote super class methods to MyClass
window.MyClass = createjs.promote(MyClass, "EventDispatcher");
This is way cleaner, easier to use, and in our tests works great!
Hope that helps :)

Categories