Fabric.js specify lineCap style - javascript

In html5 canvas it is possible to specify lineCap style for the line ends.
E.g.:
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.lineCap="round"; // <-- here lineCap is specified
ctx.moveTo(20,20);
ctx.lineTo(200,20);
Possible options are: butt (Default), round, square.
My question is:
How to specify lineCap style when creating the Line with fabric.js?
var line = new fabric.Line(
[0, 100, 200, 100],
{
strokeWidth: 5
// I presume some option should be specified here, but how is it should be called?
}
);

I found an answer
Posting it here, as it is not obvious from the fabric.js documentation:
var line = new fabric.Line(
[0, 100, 200, 100],
{
strokeWidth: 5,
strokeLineCap: "round" // <-- this makes 'round' line ends style
}
);

Related

Interpolate stroke width between points in Paper.js

I am using Paper.js to create some shapes. It has worked great so far. One thing where I am stuck is variable stroke width. I want to stroke width to change between different points just like the color changes in gradients. Here is some code:
var firstSegment = new Segment({
point: [100, 50],
handleOut: [80, 100]
});
var secondSegment = new Segment({
point: [300, 50],
handleIn: [-80, -100]
});
var path = new Path({
segments: [firstSegment, secondSegment],
strokeColor: 'black',
strokeWidth: 4
});
In the above example, the strokeWidth is 4 everywhere along the path. How can I create a path such that it starts with a stroke width of 1px and then gets 6px wide at the other end?

Paper.js - Clipping opacity for paths outside of area

I have a simple rectangle that forms the clipping area for all shapes added to the canvas, which is working great:
var area = new paper.Rectangle(
100, 100, 300, 120
);
var path = new paper.Path.Rectangle(area);
group.addChild(path);
group.clipped = true;
What I'm trying to achieve is instead of hiding the paths that fall outside of this area, they are shown with a slight opacity, something like:
Thanks in advance for any help and suggestions.
This is not a simple way as clipped, you might do it by using method intersect.
Please try this code.
// SET INITIAL
var area = new paper.Path.Rectangle(100, 100, 300, 220);
area.fillColor = 'yellow'
area.opacity = 0.2
var circle1 = new paper.Path.Circle({
center:[150, 150],
radius: 100,
fillColor: 'red'
})
// OPACITY CLIPPING
var circle2 = circle1.intersect(area)
circle1.opacity = 0.2

Change Color of Shape Mid Tween

I'm trying to make an event that changes my shapes stroke color for 5 seconds when a button is clicked, and then the shape returns to original color after the duration.
I am able to do this with clearing the entire stage and redrawing new shapes (which resets their position), but I can't figure it out with the current shapes.
Q. What's the best way to approach making a change to a shapes color, during a Tween?
I was also curious if there's a better way to handling tweening the shapes width? Currently I am relying on ScaleX and ScaleY - but this also changes the stroke's size - which is not desired.
JS Fiddle
HTML
<button id="change">Click to Change Color</button>
<canvas id="demoCanvas" width="500" height="500"></canvas>
JS
var stage,
circle;
function init() {
stage = new createjs.Stage("demoCanvas");
createjs.Ticker.setFPS(60);
createjs.Ticker.addEventListener("tick", stage);
}
function createCircle(){
circle = new createjs.Shape().set({name:"circle"});
circle.graphics.setStrokeStyle(1).beginStroke("#000").beginFill( "#FFF" ).drawCircle(0, 0, 20);
circle.x = 100;
circle.y = 100;
stage.addChild(circle);
createjs.Tween.get(circle, {loop: true})
.to({x: 225, y: 225}, 1000, createjs.Ease.getPowInOut(1))
.to({x: 100, y: 100}, 1000, createjs.Ease.getPowInOut(1));
circle2 = new createjs.Shape().set({name:"circle"});
circle2.graphics.setStrokeStyle(1).beginStroke("#000").beginFill( "#FFF" ).drawCircle(0, 0, 20);
circle2.x = 400;
circle2.y = 400;
stage.addChild(circle2);
createjs.Tween.get(circle2, {loop: true})
.to({scaleX: 2, scaleY: 2, x: 425, y: 125}, 1000, createjs.Ease.getPowInOut(1))
.to({scaleX: 1, scaleY: 1, x: 400, y: 400}, 1000, createjs.Ease.getPowInOut(1));
stage.update();
}
$( "#change" ).click(function() {
// change color
});
$(document).ready(function() {
init();
createCircle();
});
There are a few questions in this post, so I will try to answer them all:
First, a solution to most of your issues is Graphic commands. Commands provide a simple way to store graphic instructions, and change them later. Here is a simple example:
var shape = new createjs.Shape();
var colorCmd = shape.graphics.beginFill("red").command;
var rectCmd = shape.graphics.drawRect(0,0,100,100).command;
// Later
colorCmd.style = "blue";
rectCmd.w = 200;
stage.update(); // Remember to update the stage after changing properties
You can read more about commands on the createjs blog. All commands and their properties are documented in the EaselJS docs.
Change a color: I outlined this in the example above, but the short answer is to adjust the style property of a fill command. If you want to change it instantly, you can just set up a Tween.call:
Example:
createjs.Tween.get(circle, {loop: true})
.to({x: 225, y: 225}, 1000, createjs.Ease.getPowInOut(1))
.call(function(tween) {
colorCmd.style = "rgba(0, 0, 255, 0.5)"; // Change to 50% blue
})
.to({x: 100, y: 100}, 1000, createjs.Ease.getPowInOut(1));
If you want to tween the color, then you could check out the ColorPlugin, which is currently in a "Plugins" branch of TweenJS: https://github.com/CreateJS/TweenJS/tree/Plugins/extras/plugins
// Tween the color from its current value to blue.
// Note that only hex, short hex, HSL, and RGB formats are supported.
createjs.Tween.get(colorCmd).to({style:"#0000ff"});
Change the size: The example above also shows how to modify the values of a drawRect call. You can do the same with any other draw command (including moveTo, lineTo, polyStar, etc).
Scaling also works, and if you want to not scale the stroke, just set the ignoreScale parameter on the stroke style.
shape.graphics.setStrokeStyle(1, null, null, null, true);

Implementing an eraser with paperjs

I've checked, similar questions have been asked, but have been left partially answered or not answered at all.
I need to build an eraser tool with PaperJS that will be able to erase existing paths, without erasing the image underneath.
So the image can reside on the first layer, and the paths on the second. See the accompanying JSFiddle: jsfiddle which shows two attempts:
paper.install(window);
var canvas = document.getElementById("myCanvas");
paper.setup(canvas);
//the yellow background (can also be background image) which should NOT be erased
var rect = new Rectangle(new Point(0, 0), new Point(paper.view.size.width, paper.view.size.height));
var rectPath = new Path.Rectangle(rect);
rectPath.fillColor = 'yellow';
//first attempt to erase the black line
var first = paper.project.activeLayer;
var second = new Layer();
var from = new Point(50, 0);
var to = new Point(50, 100);
var path1 = new Path.Line(from, to);
path1.strokeColor = 'black';
path1.strokeWidth = 40;
var from = new Point(0, 50);
var to = new Point(100, 50);
var path2 = new Path.Line(from, to);
path2.strokeColor = 'green'; //I've tried other colors as well, this seems irrelevant
path2.strokeWidth = 40;
path2.blendMode = 'destination-out';
//So I saw this
var path = new CompoundPath({
children: [
new Path.Circle({
center: new Point(200, 50),
radius: 30
}),
new Path.Circle({
center: new Point(200, 50),
radius: 10
})
],
fillColor: 'black',
selected: true
});
//second attempt
//I need to actually erase with one line through lots of paths, not sure how to implement it with this
var path = new CompoundPath({
children: [
new Path.Line({
from: [350, 0],
to: [350, 100],
strokeWidth: 30,
strokeColor: 'green' //irrelevant it seems
}),
new Path.Line({
from: [300, 50],
to: [400, 50],
strokeWidth: 30,
strokeColor: 'white' //irrelevant it seems
})
],
strokeColor: 'black',
selected: true,
strokeWidth: 20
});
paper.view.draw();
<script src="http://tmantechblog.com/testpaperjs/js/libs/paper.js"></script>
<canvas id="myCanvas" height='500' width='500'>This does not support HTML5 canvas</canvas>
The first attempt tries to use blendMode='destination-out' but it leaves a white mark rather than a transparent path
The second implementation tries to mimic the compoundPath example provided there, but where the paths cross, no hole is produced. Also, I'm unsure how this can be used to implement an eraser across multiple paths.
Any advice on how to proceed will be appreciated. Otherwise I'll have to port my whole project either to the basic HTML 5 canvas or FabricJS, or something similar.

Place an Image inside a Polygon with Snap.svg

I have a polygon (in fact it's a hexagon) painted with Adobe's Snap.svg:
var s = Snap('#test');
var hexagon = s.paper.polygon([
0, 50,
50, 0,
100, 0,
150, 50,
100, 100,
50, 100,
0, 50
]);
hexagon.attr({
stroke: '#fff',
strokeWidth: 1
});
Instead of filling the polygon with some paint, I want to place an image inside of it. The only thing I have found in the docs is the image function, but I don't know how to insert it. Anyone any idea?
======
Final Solution:
var image = s.paper.image('http://placekitten.com/g/200/300', 0, 0, 150, 150);
image = image.pattern(0, 0, 150, 150);
...
hexagon.attr({
stroke: '#fff',
strokeWidth: 1,
fill: image
});
You can't directly fill an element with an image you have to go via a pattern.
What this means is that you need to create a pattern that contains an image and then fill the shape with the pattern.

Categories

Resources