Get width of selected layer with Sketch API - javascript

Writing my first Sketch plugin and I'm trying to get the width of a selected layer.
export default function(context) {
const selectedLayers = context.selection;
const selectedCount = selectedLayers.length;
if (selectedCount === 0) {
context.document.showMessage('Please select a circle shape layer');
} else {
selectedLayers.forEach(function (layer) {
log(layer.frame.width);
})
}
}
The log shows:
<MOUndefined: 0x6040000048f0>
The documentation states that the frame of the layer is a Rectangle and that a Rectangle has x, y, width and height properties. So I don't understand why I'm getting undefined.
I tried log(layer.frame) and I do get:
<MOMethod: 0x60400263b420 : target=0x7f9dbf5b8ee0<MSShapeGroup: 0x7f9dbf5b8ee0> Oval (691540C6-7B18-4752-9BA6-A3A298754C9A), selector=frame>
So I'm targetting it right.

try with
layer.frame().width()

Related

svg color inside fabricjs canvas not changing

i'm trying to change svg path's fill which is inside fabricjs canvas.
using this function
function changeColor(material) {
console.log(svgGroup[0].fill)
console.log(material);
if (material == 'base') {
svgGroup[0].fill = '#000000';
console.log(svgGroup[0].fill)
}
texture.needsUpdate = true;
object.children[0].material = textureMaterial;
canvas.renderAll();
}
but it doesn't updated automatically
anyone have any idea why? any thought would be helpful
i found the solution, the problem iwas i didn't set the color correctly. instead of doing this
svgGroup[0].fill = '#000000';
it should've use this
svgGroup._objects.forEach(obj => {
if (obj.id == material) {
obj.set('fill', color);
}
});
that way it is rendered when renderAll() is called

Unexpected border pattern in a grid with rectangles in p5.js

I am trying to generate a square grid like pattern in p5js that covers as much of the browser window as possible.I am using p5js in instance mode as I using this with react and I am using chrome in Win10.
Here is my code:-
var size = 15;
var height = window.innerHeight;
var width = window.innerWidth;
Sketch = (p) => {
p.setup = () => {
p.createCanvas(width,height)
p.frameRate(60);
p.noLoop();
}
p.draw = () => {
p.background(250);
p.stroke(0);
p.noFill();
for(let i =0;i*size +size <width;i++) {
for(let j=0;j*size +size<height;j++) {
p.rect(i*size,j*size,size,size);
}
}
}
p.mouseDragged = (e) => {
p.stroke(0);
let x = Math.floor(e.clientY/size);
let y = Math.floor(e.clientX/size);
p.fill(220);
p.rect(y*size,x*size,size,size);
}
}
I call p.noLoop() so it doesnt refreshes everytime and I also have a button that calls p.redraw() to change everything to default. Here is the grid and behaviour I get:
The borders of grids are of varying sizes, first they decrease then increase then decrease and so on. Also, the area around which I drag my mouse has even more weird borders(This gets resolved when I click somewhere else so is this a GPU Aliasing rendering issue?). How do I create grid with same borders throughout my screen?
Edit: When I render even a single box, it has issues. The left and upper border are fine. However the right and down borders have an extra pixel of grayish borders which seems to be the problem. How do I fix this?
Also, How does strokeWeight and rect work in p5js? If I do strokeWeight(10) and rect(3,2,50,50), does that create a 50 by 50 rectangle with 10 pixels borders all around or the borders are included in the rectangle size?

Chart.js : Multiple colors for tooltipFontColor

I know that the font color for the tooltip labels can be changed with the toolTipFontColor option, but that forces me to give one colour for all labels. Is there a way to set the colour for a label to, say, white, but then change it to red if a condition holds. I was thinking of something using the customTooltips option but any solution is welcome.
Example of what I'd like to do:
if (difference[i] >= 0) {
tooltipFontColor: "#FFF"
} else {
tooltipFontColor: "#F00"
}
The trick is that the difference array can have some values above zero and some below. I want Chart.js to somehow understand that and follow through with the colours.
Thanks!
Different Colors for Toooltip Based on Value
Preview
Script
new Chart(ctx).Line(data, {
// take over the tooltip binding
tooltipEvents: [],
onAnimationComplete: function () {
// copy of chart.js binding except that ...
Chart.helpers.bindEvents(this, ["mousemove", "touchstart", "touchmove"], function (evt) {
var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
this.eachPoints(function (point) {
point.restore(['fillColor', 'strokeColor']);
});
Chart.helpers.each(activePoints, function (activePoint) {
activePoint.fillColor = activePoint.highlightFill;
activePoint.strokeColor = activePoint.highlightStroke;
});
// ... we set the font color before the tooltip is shown
if (activePoints.length !== 0) {
if (activePoints[0].value >= 0)
this.options.tooltipFontColor = "#FFF";
else
this.options.tooltipFontColor = "#F00";
}
this.showTooltip(activePoints);
});
}
});
Fiddle - http://jsfiddle.net/uajz17yp/

Fabric.js: How to observe object:scaling event and update properties dynamically?

I'm trying to get the shape properties to dynamically update when the shape is being scaled.
Here's a fiddle: http://jsfiddle.net/anirudhrantsandraves/DAjrp/
The console log commands:
console.log('Width = '+scaledObject.currentWidth);
console.log('Height = '+scaledObject.currentHeight);
are supposed to dynamically display the height and width of the shape as it is being scaled.
The properties remain the same in the console when the shape gets scaled. However, when I select the object again and scale it, the previous values of the properties are displayed.
Is there a way to make this dynamic?
getWidth() and getHeight() are used to get the current width and height in Fabric.js.
So in "object:scaling" event:
canvas.on('object:scaling', onObjectScaled);
function onObjectScaled(e)
{
var scaledObject = e.target;
console.log('Width = '+scaledObject.getWidth());
console.log('Height = '+scaledObject.getHeight());
}
will serve your purpose.
Updated fiddle — http://jsfiddle.net/DAjrp/2/
Just in case, if you wanted to get the scaled height
canvas.on("object:scaling", (e) => {
canvas.getActiveObjects().forEach((o) => {
// if it's scaled then just multiple the height by scaler
const objHeight = o.scaleY ? o.height * o.scaleY : o.height;
// ...
});
});

HTML5 photoshop like polygonal lasso selection

Im looking to build a tool to cut out a portion of a photo by letting the user create a closed shape. The user should be able to start drawing lines. From point a to point b, to c, e, d, e, f .... to eventually point a again to close the shape.
I want to use the HTML5 canvas for this. I think this could be a good fit and I'm thinking about using something like flashcanvas as fallback for IE/older browsers?
Is there any tutorial/open source application that I could use to build this sort of thing?
This is the first time I'm going to build an application using HTML5 canvas so are there any pitfalls I should worry about?
I think this is advanced usage of canvas. You have to know the basics, how to draw, how to use layers, how to manipulate pixels. Just ask google for tutorials.
Assuming you know about the previous, I'll give it a try. I've never done that before but I have an idea :
You need 3 canvas :
the one containing your picture (size of your picture)
a layer where the user draw the selection shape (size of your picture, on top of the first canvas)
a result canvas, will contain your cropped picture (same size, this one doesn't need to be displayed)
When the user click on your picture : actually, he clicks on the layer, the layer is cleared and a new line begins.
When he clicks on it another time, the previous started line is drawn and another one begins, etc... You keep doing this until you click on a non-blank pixel (which means you close the shape).
If you want the user to preview the lines, you need another canvas ( explained here http://dev.opera.com/articles/view/html5-canvas-painting/#line )
When the shape is closed, the user has to click inside or outside the shape to determine which part he wants to select. You fill that part with a semi-transparent gray for example ( flood fill explained here http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool/ )
Now the layer canvas contains a colored shape corresponding to the user selection.
Get the pixel data from your layer and read through the array, every time you find a non-blank pixel at index i, you copy this pixel from your main canvas to the result canvas :
/* First, get pixel data from your 3 canvas into
* layerPixData, resultPixData, picturePixData
*/
// read the entire pixel array
for (var i = 0 ; i < layerPixData.length ; i+=4 ) {
//if the pixel is not blank, ie. it is part of the selected shape
if ( layerPixData[i] != 255 || layerPixData[i+1] != 255 || layerPixData[i+2] != 255 ) {
// copy the data of the picture to the result
resultPixData[i] = picturePixData[i]; //red
resultPixData[i+1] = picturePixData[i+1]; //green
resultPixData[i+2] = picturePixData[i+2]; //blue
resultPixData[i+3] = picturePixData[i+3]; //alpha
// here you can put the pixels of your picture to white if you want
}
}
If you don't know how pixel manipulation works, read this https://developer.mozilla.org/En/HTML/Canvas/Pixel_manipulation_with_canvas
Then, use putImageData to draw the pixels to your result canvas. Job done !
If you want to move lines of your selection, way to go : http://simonsarris.com/blog/225-canvas-selecting-resizing-shape
Here is how you should do that:
The code at the following adds a canvas on top of your page and then by clicking and dragging on that the selection areas would be highlighted. What you need to do after that is to make a screenshot from the underlying page and also a mask layer out of the created image in your canvas and apply that to the screenshot, just like how it is shown in one other answers.
/* sample css code for the canvas
#overlay-canvas {
position: absolute;
top: 0;
left: 0;
background-color: transparent;
opacity: 0.4;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
}
*/
function getHighIndex(selector) {
if (!selector) { selector = "*" };
var elements = document.querySelectorAll(selector) ||
oXmlDom.documentElement.selectNodes(selector);
var ret = 0;
for (var i = 0; i < elements.length; ++i) {
if (deepCss(elements[i],"position") === "static")
continue;
var temp = deepCss(elements[i], "z-index");
if (temp != "auto")
temp = parseInt(temp, 10) || 0;
else
continue;
if (temp > ret)
ret = temp;
}
return ret;
}
maxZIndex = getHighIndex();
$.fn.extend({
lasso: function () {
return this
.mousedown(function (e) {
// left mouse down switches on "capturing mode"
if (e.which === 1 && !$(this).is(".lassoRunning")) {
var point = [e.offsetX, e.offsetY];
$(this).addClass("lassoRunning");
$(this).data("lassoPoints", [point]);
$(this).trigger("lassoStart", [point]);
}
})
.mouseup(function (e) {
// left mouse up ends "capturing mode" + triggers "Done" event
if (e.which === 1 && $(this).is(".lassoRunning")) {
$(this).removeClass("lassoRunning");
$(this).trigger("lassoDone", [$(this).data("lassoPoints")]);
}
})
.mousemove(function (e) {
// mouse move captures co-ordinates + triggers "Point" event
if ($(this).is(".lassoRunning")) {
var point = [e.offsetX, e.offsetY];
$(this).data("lassoPoints").push(point);
$(this).trigger("lassoPoint", [point]);
}
});
}
});
function onLassoSelect() {
// creating canvas for lasso selection
var _canvas = document.createElement('canvas');
_canvas.setAttribute("id", "overlay-canvas");
_canvas.style.zIndex = ++maxZIndex;
_canvas.width = document.width
_canvas.height = document.height
document.body.appendChild(_canvas);
ctx = _canvas.getContext('2d'),
ctx.strokeStyle = '#0000FF';
ctx.lineWidth = 5;
$(_canvas)
.lasso()
.on("lassoStart", function(e, lassoPoint) {
console.log('lasso start');
var pos = lassoPoint;
ctx.beginPath();
ctx.moveTo(pos[0], pos[1]);
console.log(pos);
})
.on("lassoDone", function(e, lassoPoints) {
console.log('lasso done');
var pos = lassoPoints[0];
ctx.lineTo(pos[0], pos[1]);
ctx.fill();
console.log(pos);
})
.bind("lassoPoint", function(e, lassoPoint) {
var pos = lassoPoint;
ctx.lineTo(pos[0], pos[1]);
ctx.fill();
console.log(pos);
});
}

Categories

Resources