globalCompositeOperation at jCanvas - javascript

How can I integrate globalCompositeOperation(or any other plugin which will give me 'multiply' color manipulation) into jCanvas jQuery plugin?
// How do I get this working? //
var ctx = document.getElementById('canvas').getContext('2d');
ctx.globalCompositeOperation = 'darker';
// With this - //
$("canvas").drawArc({
fillStyle: "#c7302a",
x: 100, y: 100,
radius: 50
});
$("canvas").drawArc({
fillStyle: "#395797",
x: 170, y: 100,
radius: 50,
opacity: 1
});

For the record, jCanvas has a compositing property, the value for which maps to ctx.globalCompositeOperation.
$("canvas").drawArc({
fillStyle: "#c7302a",
x: 100, y: 100,
radius: 50,
compositing: 'darker'
});
-Caleb

Okay I solved it. After struggling with it for hours, it was too simple:
I used context blender plugin.
JS code:
$("#canvasReal").drawArc({ // Draw on the real canvas
fillStyle: "#c7302a",
x: 100, y: 100,
radius: 50
});
$("#canvasOff").drawArc({ // Draw on the off screen canvas
fillStyle: "#395797",
x: 150, y: 100,
radius: 50
});
// Blend off-screen canvas onto the real canvas
var over = canvasOff.getContext('2d');
var under = canvasReal.getContext('2d');
over.blendOnto(under,'multiply');
HTML code:
<canvas width="500" height="250" id="canvasReal"></canvas>
<canvas width="500" height="250"id="canvasOff" style="display:none;"></canvas>

Related

How to fix FabricJS scaled polygon clipping offset

I'am trying to clip the FabricJS rect shape to the polygon shape. The clipping works okay until the polygon shape which need to be clipped is now scaled. After this there is some weird offset that is caused by the polygon clipping.
Can anyone help me how can i fix the function to prevent the polygon offset issue when clip object is scaled.
This is how it looks before scalling. The clipping works fine
Image => https://i.imgur.com/Eop2YJh.png
And then there is the problem when the polygon is scaled.
2: Image => https://i.imgur.com/ICkP8SG.png
Here is the code on fiddle with the clipping function
https://jsfiddle.net/0xpvc9uq/
So if there is anyone who knows whats the point and how can I fix it I would appriciate it.
Thx
var canvas = new fabric.Canvas('c');
var rect1 = new fabric.Rect({
left: 0, top: 0,
width: 900, height: 900,
fill: 'blue',
selectable: false,
clipTo: clipRegion,
scaleX: 1.5,
scaleY: 1.5
});
var clipPoly = new fabric.Polygon([
{ x: 180, y: 10 },
{ x: 300, y: 50 },
{ x: 300, y: 180 },
{ x: 180, y: 220 }
], {
originX: 'left',
originY: 'top',
left: 180,
top: 10,
fill: 'transparent', /* use transparent for no fill */
strokeWidth: 0,
selectable: false,
strokeWidth: 1,
stroke: "red",
scaleX: 1.3,
scaleY: 1.3
});
canvas.add(rect1, clipPoly);
function clipRegion (ctx) {
rect1.setCoords();
const clipObj = clipPoly;
const scaleXTo1 = (1 / rect1.scaleX);
const scaleYTo1 = (1 / rect1.scaleY);
ctx.save();
const ctxLeft = -( rect1.width / 2 ) - clipObj.strokeWidth - rect1.strokeWidth;
const ctxTop = -( rect1.height / 2 ) - clipObj.strokeWidth - rect1.strokeWidth;
ctx.translate( ctxLeft, ctxTop );
ctx.scale(scaleXTo1, scaleYTo1);
ctx.rotate((rect1.angle * -1) * (Math.PI / 180));
ctx.beginPath();
const matrix = clipPoly.calcTransformMatrix();
let points = [];
clipObj.points.forEach( (point) => {
points.push({
x: ((point.x * matrix[0]) + (clipObj.strokeWidth * clipObj.scaleX)) - rect1.oCoords.tl.x,
y: ((point.y * matrix[3]) + (clipObj.strokeWidth * clipObj.scaleY)) - rect1.oCoords.tl.y
});
});
ctx.moveTo(points[0].x, points[0].y);
points.forEach((point) => {
ctx.lineTo(point.x, point.y);
});
ctx.lineTo(points[0].x, points[0].y);
ctx.closePath();
ctx.restore();
}
I discovered that there is also another approach that can be used and that solves all the problem.
The clipRegion function now looks like:
function clipRegion (ctx) {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
clipPoly.render(ctx);
ctx.restore();
}
Which makes the rendering okay. If still anyone have other way to fix the above problem, I would like to see the answer

how to make rounded corners on polygon with kineticjs

I am using kineticjs to do some HTML5 graphics, and I would like to make a rounded corner on a polygon. How can I do this? At the moment I have this polygon:
var poly = new Kinetic.Polygon({
points: [50, 100, 180, 100, 180, 120, 200, 120, 200, 180, 50, 180, 50, 100],
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 1
});
Please note that I want the lower left corner to be a rounded corner with a radius of 10. How can I do that?
Use Kinect.Shape instead
var poly = new Kinetic.Shape({
drawFunc: function(canvas) {
var context = canvas.getContext();
var radius=10;
context.beginPath();
context.moveTo(50, 100);
context.lineTo(180, 100);
context.lineTo(180, 120);
context.lineTo(200, 120);
context.lineTo(200, 180);
//context.lineTo(50, 180);
context.arcTo(50, 180, 50, 180-radius, radius);
context.closePath();
canvas.fillStroke(this);
},
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 1
});

How can I create a transparent shape within an existing shape using KineticJS

Is there a simple way to "stamp" a transparent section from within another shape (or layer) using KineticJS?
For example, using the following code:
var stage = new Kinetic.Stage({
container: 'canvas',
width: 100,
height: 100
});
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 1,
y: 1,
width: 96,
height: 96,
fill: 'green',
stroke: 'black',
strokeWidth: 2
});
layer.add(rect);
var star = new Kinetic.Star({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
numPoints: 5,
innerRadius: 15,
outerRadius: 40,
fill: 'yellow'
});
layer.add(star);
stage.add(layer);
How would I make the star shape within the green box transparent so that elements behind the canvas are visible. Here's an example fiddle: http://jsfiddle.net/ZPVxa/
I have looked into filters, and I think that may be the way to go, but I can't seem to find what I'm looking for in the documentation.
You can use a Kinetic Shape Object to do custom drawing, including your star cut-out
The Shape gives you access to a context which gives you access to the full range of canvas operations.
The operation needed for “cutting” your star from your background is globalCompositeOperation.
The “destination-out” composite will cut out the next drawn shape (your star) from any existing drawings (your green rect).
Here is how you draw the green rect and use composition to cut out the star.
var rect = new Kinetic.Shape({
drawFunc: function(canvas){
context=canvas.getContext("2d");
context.save();
context.beginPath();
context.rect(0,0,96,96);
context.fillStyle="green";
context.fill();
context.globalCompositeOperation="destination-out";
drawStar(context,45,50,5,40,15);
canvas.fillStroke(this);
context.restore();
},
width: 96,
height: 96,
fill: 'green',
stroke: 'black',
strokeWidth: 2
});
Since the star is not a native canvas shape, you will also need this code to draw a star:
function drawStar(ctx,cx,cy,spikes,outerRadius,innerRadius){
var rot=Math.PI/2*3;
var x=cx;
var y=cy;
var step=Math.PI/spikes;
ctx.strokeSyle="#000";
ctx.beginPath();
ctx.moveTo(cx,cy-outerRadius)
for(i=0;i<spikes;i++){
x=cx+Math.cos(rot)*outerRadius;
y=cy+Math.sin(rot)*outerRadius;
ctx.lineTo(x,y)
rot+=step
x=cx+Math.cos(rot)*innerRadius;
y=cy+Math.sin(rot)*innerRadius;
ctx.lineTo(x,y)
rot+=step
}
ctx.lineTo(cx,cy-outerRadius)
ctx.closePath();
ctx.fill();
}
That’s pretty much it!
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/VVrZT/
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.3.min.js"></script>
<script defer="defer">
var stage = new Kinetic.Stage({
container: 'container',
width: 300,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);
var rect = new Kinetic.Shape({
drawFunc: function(canvas){
context=canvas.getContext("2d");
context.save();
context.beginPath();
context.rect(0,0,96,96);
context.fillStyle="green";
context.fill();
context.globalCompositeOperation="destination-out";
drawStar(context,45,50,5,40,15);
canvas.fillStroke(this);
context.restore();
},
width: 96,
height: 96,
fill: 'green',
stroke: 'black',
strokeWidth: 2
});
layer.add(rect);
layer.draw();
function drawStar(ctx,cx,cy,spikes,outerRadius,innerRadius){
var rot=Math.PI/2*3;
var x=cx;
var y=cy;
var step=Math.PI/spikes;
ctx.strokeSyle="#000";
ctx.beginPath();
ctx.moveTo(cx,cy-outerRadius)
for(i=0;i<spikes;i++){
x=cx+Math.cos(rot)*outerRadius;
y=cy+Math.sin(rot)*outerRadius;
ctx.lineTo(x,y)
rot+=step
x=cx+Math.cos(rot)*innerRadius;
y=cy+Math.sin(rot)*innerRadius;
ctx.lineTo(x,y)
rot+=step
}
ctx.lineTo(cx,cy-outerRadius)
ctx.closePath();
ctx.fill();
}
</script>
</body>
</html>

Drawing an arc in KineticJS

I know you can draw a wedge using a Kinetic.Wedge:
var compassArc = new Kinetic.Wedge({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
angleDeg: 60,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
rotationDeg: -90
});
This draws a "pizza slice" with a black outline around the whole thing. I just want the "crust" of the pizza, with no straight lines coming back to the center of the circle. How can I do this?
Setting the fill to null removes the red but leaves the outline.
How about creating a custom shape fot this using arc?
http://www.html5canvastutorials.com/tutorials/html5-canvas-arcs/
Please keep in mind that not to close path and not to fill strokes. if so, you will get what you want. It is a KineticJS object, so that you can drag around if you want.
Here is the working example.
http://jsfiddle.net/bighostkim/WzxxH/
var arc = new Kinetic.Shape({
drawFunc: function(canvas) {
var context = canvas.getContext();
var x = stage.getWidth() / 2;
var y = stage.getHeight()/2;
var radius = 70;
var startAngle = 1 * Math.PI;
var endAngle = 0 * Math.PI;
var context = canvas.getContext('2d');
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, false);
//context.closePath();
canvas.stroke(this);
},
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4,
draggable:true
});
allenhwkim answer is a bit outdated and has some problems. For example the kinetic dash array would not work. So here is a revised version:
var arc = new Kinetic.Shape({
x: 100,
y: 100,
stroke: '#000',
strokeWidth: 4,
dash: [8, 4],
drawFunc: function(context) {
var radius = 50;
var startAngle = 1 * Math.PI;
var endAngle = 0 * Math.PI;
context.beginPath();
context.arc(0, 0, radius, startAngle, endAngle, false);
context.fillStrokeShape(this);
},
draggable:true
});
There is a Kinetic.Arc class which you can use.
Make outerRadius equal to innerRadius and you will get what you want.
this.arc = new Kinetic.Arc({
innerRadius: 90,
outerRadius: 90,
stroke: 'red',
strokeWidth: 2,
angle: 60,
rotationDeg: 210
});

Issue with Mouseover event in KineticJS

I am trying to do a bit of experimentation with KinetiJs Canvas library. What I have done below is - Draw a Rectangle, and whenever there is a mouseover I want a line to be drawn between specific points.
The problem is, I do not see any line when a mouseover happens.
I have tried checking if the onmousemove function gets called or not and it does get called, but the line doesn't get drawn. Can anyone please explain why?
$(document).ready(function () {
var stage = new Kinetic.Stage({
container: "sketchcanvas",
width: 600,
height: 600
});
var layer = new Kinetic.Layer();
var rect = new Kinetic.Rect({
x: 50,
y: 50,
width: 500,
height: 500,
fill: "#00D2FF",
stroke: "black",
strokeWidth: 4
});
rect.on("mousemove", function () {
var mousePos = stage.getMousePosition();
var x = mousePos.x;
var y = mousePos.y;
var line = new Kinetic.Line({
points: [60, 60, 80, 80, 100, 200],
stroke: "black",
strokeWidth: 15,
lineCap: 'round',
lineJoin: 'round'
});
layer.add(line);
});
layer.add(rect);
stage.add(layer);
});
In KineticJS, after you make alterations or additions to a layer, you need to draw() to the layer for effects to show
...
layer.add(line);
layer.draw();

Categories