HTML5 Canvas Transparent Stroke on Custom Shape - html5-canvas

I am new to HTML5 Canvas, and have searched a few top sites and other questions here about this issue I am having. All I am wanting to do create a clear 0 pixel stroke on this custom shape cloud I am practicing with.
But is this possible? With my current codes, my cloud has a mini black outline in Google Chrome.
How do I fix this?
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
// begin custom shape
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
// complete custom shape
context.closePath();
context.lineWidth = 0;
context.fillStyle = 'pink';
context.fill();
context.strokeStyle = 'none';
context.stroke();
</script>

Related

Reset the skewing values in a fabric object

I have a fabric ellipse object which is scaled and skewed. I want to recreate the same ellipse with no scaling and skewing. I assume this could be achieved by calculating new values for rx,ry and angle by offseting the scaling and skewing values. I managed to offset the scaling values, but I am not able to figure out the calculations to offset the skew values.
Thanks in advance for any help.
Jsfiddle - https://jsfiddle.net/jwp2yysh/
Please see the sample code. I want the blue ellipse to alligned inline with the red ellipse.
var canvas = new fabric.Canvas('c');
var redEllipse = new fabric.Ellipse({
rx: 80,
ry: 50,
originX: 'center',
originY: 'center',
fill: '',
stroke: 'red',
strokeWidth: 1,
top: 180,
left: 240,
angle: 30,
scaleX: 1.23,
scaleY: 1.4,
skewX: 25,
skewY: 0
});
canvas.add(redEllipse);
var blueEllipse = new fabric.Ellipse({
rx: redEllipse.rx * redEllipse.scaleX,
ry: redEllipse.ry * redEllipse.scaleY,
originX: 'center',
originY: 'center',
fill: '',
stroke: 'blue',
strokeWidth: 1,
top: redEllipse.top,
left: redEllipse.left,
angle: redEllipse.angle * redEllipse.scaleY / redEllipse.scaleX,
scaleX: 1,
scaleY: 1,
skewX: 0,
skewY: 0
});
canvas.add(blueEllipse);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.20/fabric.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>
I assume you are looking for something like this JSFiddle.
var canvas = new fabric.Canvas('c');
var redEllipse = new fabric.Ellipse({
rx: 80,
ry: 50,
originX: 'center',
originY: 'center',
fill: '',
stroke: 'red',
strokeWidth: 1,
top: 180,
left: 240,
angle: 30,
scaleX: 1.23,
scaleY: 1.4,
skewX: 0,
skewY: 0
});
canvas.add(redEllipse);
var blueEllipse = new fabric.Ellipse({
rx: redEllipse.rx * redEllipse.scaleX - 10,
ry: redEllipse.ry * redEllipse.scaleY - 10,
// rx:80*1.23,
//ry:50*1.4,
originX: 'center',
originY: 'center',
fill: '',
stroke: 'blue',
strokeWidth: 1,
top: redEllipse.top,
left: redEllipse.left,
angle: redEllipse.angle,
//angle:30,
scaleX: 1,
scaleY: 1,
skewX: 0,
skewY: 0
});
canvas.add(blueEllipse);
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.21/fabric.min.js"></script>
<canvas id="c" width="500" height="500"></canvas>
From what I could understand, your calculation of rx and ry is correct. The problem with calculating the angle using the formula you have mentioned in the code is probably not taking into account the skew-ness of the original ellipse.
A simpler way would be to replicate the angle redEllipse.angle to make the new ellipse inline.
To make it inside the original one, you just need to reduce the rx and ry values by some common factor (I have used 10).

Fabric toDataUrl with multiplier not working as expected

In my code I created method to clip images using fabric shapes. I have used stackoverflow answer for achieving this. Somehow after using this method I cannot render the canvas using default fabric canvas render method.
var img01URL = 'https://www.google.com/images/srpr/logo4w.png';
var img02URL = 'http://fabricjs.com/lib/pug.jpg';
var canvas = new fabric.Canvas('c');
document.getElementById('download').addEventListener('click', function() {
canvas.renderAll();
this.href = canvas.toDataURL({
format: 'png',
multiplier: 2
});
this.download = "test.png";
}, false);
var clipRect1 = new fabric.Rect({
originX: 'left',
originY: 'top',
angle: 90,
left: 195,
top: 0,
width: 200,
height: 200,
fill: '#DDD', /* use transparent for no fill */
strokeWidth: 1,
lockMovementX: true,
lockMovementY: true,
angle: 5,
stroke: 'red'
});
var pugImg = new Image();
pugImg.onload = function (img) {
var pug = new fabric.Image(pugImg, {
angle: 0,
width: 500,
height: 500,
left: 245,
top: 35,
scaleX: 0.3,
scaleY: 0.3,
clipName: 'pug',
clipTo: function(ctx) {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
clipRect1.render(ctx);
ctx.restore();
}
});
canvas.add(pug);
};
pugImg.src = img02URL;
pugImg.setAttribute('crossOrigin', 'anonymous');
#c {
border:0px solid #ccc;
}
<script src="//cdn.bootcss.com/fabric.js/1.5.0/fabric.js"></script>
<canvas id="c" width="500" height="400"></canvas>
<a id="download">Download as image</a>
Your problem is the multiplier.
When using that kind of clipTo functions, you are setting the transform of canvas to plain. When rendering with canvas with multiplier, the base canvas transformation is scaled by the multiplier.
Your rect will be drawn without this transform ( because of setTransform(1,0,0,1,0,0) and will clip out the image.
Instead of setting the transform to [1,0,0,1,0,0] you should set to the invers of the current transformation of the object you are clipping.
var img01URL = 'https://www.google.com/images/srpr/logo4w.png';
var img02URL = 'http://fabricjs.com/lib/pug.jpg';
var canvas = new fabric.Canvas('c');
document.getElementById('download').addEventListener('click', function() {
var data = canvas.toDataURL({
format: 'png',
multiplier: 2
});
console.log(data);
//var img = document.getElementById('export');
//img.src = data;
}, false);
var clipRect1 = new fabric.Rect({
originX: 'left',
originY: 'top',
angle: 90,
left: 195,
top: 0,
width: 200,
height: 200,
fill: '#DDD', /* use transparent for no fill */
strokeWidth: 1,
lockMovementX: true,
lockMovementY: true,
stroke: 'red',
angle: 5
});
var pugImg = new Image();
pugImg.onload = function (img) {
var pug = new fabric.Image(pugImg, {
angle: 0,
width: 500,
height: 500,
left: 245,
top: 35,
scaleX: 0.3,
scaleY: 0.3,
clipName: 'pug',
clipTo: function(ctx) {
ctx.save();
var myMatrix = this.calcTransformMatrix();
myMatrix = fabric.util.invertTransform(myMatrix);
ctx.transform.apply(ctx, myMatrix);
clipRect1.render(ctx);
ctx.restore();
}
});
canvas.add(pug);
};
pugImg.src = img02URL;
#c {
border:0px solid #ccc;
}
<script src="//www.deltalink.it/andreab/fabric/fabric.js"></script>
<canvas id="c" width="500" height="400"></canvas>
<a id="download">Download as image</a>
<img id="export" >

dc.js barchart and brush on issue

I am trying to implement interactive data visualization using DC,D3 and CrossFilter JS. But I am facing three issue.
Width of the bar in the bar chart
Brush is solid black
X,Y-Axis lines are too thick.
I would like to increase width of the bar and like to have Brush on feature with transparent color.
code:
dateChart.width(750)
.margins({top: 10, right: 50, bottom: 30, left: 40})
.elasticY(true)
.dimension(timeDim)
.group(dates)
.brushOn(true)
.gap(65)
.transitionDuration(500)
.centerBar(true)
// .xUnits(function(){return 10;})
.round(d3.time.day.round)
// .renderlet(colorRenderlet)
.x(d3.time.scale()
.domain([new Date(2016, 0, 1), new Date(2016, 0, 31)])
.rangeRound([0, 1 * 90]))
.renderHorizontalGridLines(true)
.filter([new Date(2016, 0, 1), new Date(2016, 0, 1)])
.xAxis().tickFormat();
//.fluctuationChart.yAxis().ticks(5);

Vertical text alignment in Firefox differs from other browsers in KineticJS

The vertical alignment of text seems to be different in different browsers when working with KineticJS. I created two JSFiddles that illustrate the problem: In the first, the text is rendered to a raw HTML5 canvas without the use of KineticJS (see Raw HTML5 Example). In this case, the text is aligned the same way in Chrome and FF. Here's the JS-code for raw HTML5 canvas:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
xOrigin = 10;
context.beginPath();
context.rect(xOrigin, 90, 107, 12);
context.fillStyle = 'yellow';
context.fill();
context.lineWidth = 2;
context.strokeStyle = 'black';
context.stroke();
context.font = '11px Calibri';
context.fillStyle = 'black';
context.fillText('Hello World! Calibri', xOrigin + 9, 100);
xOrigin = 141;
context.beginPath();
context.rect(xOrigin, 90, 103, 12);
context.fillStyle = 'cyan';
context.fill();
context.lineWidth = 2;
context.strokeStyle = 'black';
context.stroke();
context.font = '11px Arial';
context.fillStyle = 'black';
context.fillText('Hello World! Arial', xOrigin + 9, 100);
However, when KineticJS is used, the text in Arial is placed one pixel higher in FF than in Chrome (see KineticJS Example). Here's the code for the KineticJS example:
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var xOrigin = 10;
var rect = new Kinetic.Rect({
x: xOrigin,
y: 90,
width: 107,
height: 12,
fill: 'yellow',
stroke: 'black',
strokeWidth: 2
});
var simpleText = new Kinetic.Text({
x: xOrigin + 9,
y: 90,
text: 'Hello World! Calibri',
fontSize: 11,
fontFamily: 'Calibri',
fill: 'black'
});
layer.add(rect);
layer.add(simpleText);
xOrigin = 141
var rect = new Kinetic.Rect({
x: xOrigin,
y: 90,
width: 103,
height: 12,
fill: 'cyan',
stroke: 'black',
strokeWidth: 2
});
var simpleText = new Kinetic.Text({
x: xOrigin + 9,
y: 90,
text: 'Hello World! Arial',
fontSize: 11,
fontFamily: 'Arial',
fill: 'black'
});
layer.add(rect);
layer.add(simpleText);
stage.add(layer);
Is there a way to render text consistently across FF and Chrome with KineticJS? Unfortunately, there seems to be no text-baseline property in KineticJS (see here). And why is it rendered correctly when working on the raw HTML5 canvas? Is this a KineticJS bug or did I miss something?

Loading image with Kineticjs

I'm having trouble loading a simple image into a layer. Sometimes it appears, others it doesn't.
<div id="container0" style="position:absolute; top:5px; left: 5px;"></div>
<script>
Layer = new Kinetic.Layer();
window.onload = function () {
stage = new Kinetic.Stage({ container: "container0", width: 1000, height: 500 });
stage.add(Layer);
var img = new Image();
img.src = "Images/Start.png"
Image= new Kinetic.Image({ x: 250, y: 150, width: 251, height: 231,image: img});
Layer.add(Image)
Layer.draw();
};
</script>
I guess it showing or not depends on if the image load time is quick enough, but I'm probably not doing it right.
Any help is appreciated. Thanks
Use image.onload:
img.onload = function(){
Image= new Kinetic.Image({ x: 0, y: 0, width: 251, height: 231,image: img});
layer.add(Image);
layer.draw();
}
http://jsfiddle.net/lavrton/WeVW4/1/

Resources