How to add a border radius to a Textbox in FabricJS - javascript

I can't add border radius to Textbox using FabricJS and make it working with edit text.
I Added a Textbox into FabricJS, i used a snippet to add background color to padding.
The only way it worked, i added a rect and grouped it with Textbox, when i did it, the edit was gone.
I created a fiddle for it:
canvas = new fabric.Canvas('main-canvas', {
allowTouchScrolling: true
});
context = canvas.getContext("2d");
var textbox = new fabric.Textbox('Test', {
left: (canvas.width - 150) / 2, // 150 is width of text box
top: (canvas.height - 25) / 2, // 25 is height of text box
width: 150,
fontSize: 20,
fontFamily: 'rubik',
originX: 'center',
originY: 'center',
rx: 10,
ry: 10,
textAlign: 'center',
fill: "#ffffff",
backgroundColor: '#ffffff',
textBackgroundColor: '#ffffff',
padding: 10
});
textbox.setGradient('fill', {
x1: -textbox.width / 2,
y1: 0,
x2: textbox.width / 2,
y2: 0,
colorStops: {
0: "black",
0.5: "red",
1: "blue"
}
});
textbox.setControlsVisibility({
mt: false,
mb: false,
ml: false,
mr: false,
bl: false,
br: false,
tl: false,
tr: false,
mtr: false
});
textbox.set({ // enable padding background color
_getNonTransformedDimensions(){ // Object dimensions
return new fabric.Point(this.width, this.height).scalarAdd(this.padding);
},
_calculateCurrentDimensions(){ // Controls dimensions
return fabric.util.transformPoint(this._getTransformedDimensions(), this.getViewportTransform(), true);
}
});
textbox.borderColor = "#fff";
canvas.add(textbox).setActiveObject(textbox);
canvas.renderAll();
body{
background: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.js"></script>
<div id="canvas-container">
<canvas id="main-canvas" width="300" height="300"></canvas>
</div>
I want the text to have a border radius and able to edit the text.

Related

How do I dynamically stretch an image in Phaser 3?

I'm trying to stretch an image dynamically so it expands in one direction in my Phaser 3 game. I've tried using a Tween with scaleX but there's a problem.
The first one is what I have. An image object in Phaser that I want to stretch. The second bar is what happens when I use scaleX. I guess it's what normally should happen, but not what I need. I need it like bar three. The left side of the image should stay aligned and only the right side should stretch. ALso I want to do this in an animation, so it should be something I can use with tweens or similar solutions. It needs to be possible to do it on any angle, so I can't just change the x-position. It has to be possible at any angle, when I don't know what the angle is going to be.
Does anyone know how to do that?
I'm not sure how your code looks like, but here is how I would solve it:
(If I would have to use scaleX and tween)
Although I don't know: what you want/need/mean with the "...on any angle..., here to know/see your code would be good.
just set the origin of the gameObject to 0 since the default is center
adjust the x position to compensate for the new origin position.
Here a runnable example:
(Tween starts a scaleX = 0 to better illustrate, where the origin is)
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#ffffff',
scene: {
create: create
}
};
var game = new Phaser.Game(config);
function create ()
{
var original = this.add.rectangle(225, 75, 200, 50, 0x0);
var defaultOrigin = this.add.rectangle(225, 150, 200, 50, 0x0);
// calculate the offset -100 = half width
var setOrigin = this.add.rectangle(225 - 100, 200, 200, 50, 0x0).setOrigin(0);
var setOriginAtAnAngle = this.add.rectangle(225 - 100, 275, 200, 50, 0x0)
.setOrigin(0)
.setAngle(25);
var setOriginAtAnAngle2 = this.add.rectangle(225 - 100, 375, 200, 50, 0x0)
.setOrigin(0, .5)
.setAngle(25);
// rotation in degrees
//setOriginAtAnAngle.angle = 25;
/* origin point */
this.add.rectangle(225, 75, 5, 5, 0xFFA701).setOrigin(0.5);
this.add.rectangle(225, 150, 5, 5, 0xFFA701).setOrigin(0.5);
this.add.rectangle(225 - 100, 200, 5, 5, 0xFFA701).setOrigin(0.5);
this.add.rectangle(225 - 100, 275, 5, 5, 0xFFA701).setOrigin(0.5);
this.add.rectangle(225 - 100, 375, 5, 5, 0xFFA701).setOrigin(0.5, 1);
/* Just code to improve the display */
this.add.line(0, 0, 150, 25, 150, 400, 0x0000ff).setOrigin(0);
this.add.text(150, 75, ' Base Box', { fontFamily: 'Arial', fontSize: '20px', color: '#fff' }).setOrigin(0, .5);
this.add.text(150, 150, ' Origin: default (Center)', { fontFamily: 'Arial', fontSize: '20px', color: '#f00' }).setOrigin(0, .5);
this.add.text(150, 200, ' Origin: 0 (TopLeft)', { fontFamily: 'Arial', fontSize: '20px', color: '#0f0' }).setOrigin(0, -.5);
this.add.text(150, 290, ' Origin: 0 (TopLeft) with angle', { fontFamily: 'Arial', fontSize: '20px', color: '#0f0' })
.setOrigin(0, -.5)
.setAngle(25);
this.add.text(150, 360, ' Origin: 0 (CenterLeft) with angle', { fontFamily: 'Arial', fontSize: '20px', color: '#0f0' })
.setOrigin(0, -.5)
.setAngle(25);
this.text = this.add.text(100, 12, 'Click to replay tween!', { fontFamily: 'Arial', fontSize: '20px', color: '#0000ff', backgroundColor: '#ffffff', fontStyle:'Bold' });
this.tween = this.tweens.add({
targets: [defaultOrigin, setOrigin, setOriginAtAnAngle, setOriginAtAnAngle2],
duration: 3000,
scaleX:{from:0, to:2},
ease: 'Power0',
onStart: _ => this.text.setText('Tween is running!'),
onActive: _ => this.text.setText('Tween is running!'),
onComplete: _=> this.text.setText('Click to replay tween!')
});
this.input.on('pointerdown', _=> {
if(!this.tween.isPlaying()){
this.tween.restart();
}
})
}
canvas {
transform: scale(.5) translate(-50%, -50%)
}
<script src="//cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.min.js"></script>
Update:
Origin's are now marked in the example, with a yellow point, for clarity.

JointJs: Define a custom shape with Node.Js

I am a bit confused by the fact, that in my application it doesn't seem to work to define custom shapes using JointJs in combination with NodeJs. I was trying the following code:
const joint = require('jointjs')
const rectWidth = 130
const rectHeight = 65
joint.shapes.standard.Rectangle.define('examples.CustomRectangle', {
attrs: {
body: {
refWidth: '100%',
refHeight: '100%',
strokeWidth: 5,
stroke: '#000000',
strokeDasharray: rectWidth + ',' + rectHeight,
fill: 'white'
},
label: {
textVerticalAnchor: 'middle',
textAnchor: 'middle',
refX: '50%',
refY: '50%',
fontSize: 14,
fill: '#333333'
}
}
})
console.log(joint)
export class ElementFactory {
createDatastore (x, y) {
return new joint.shapes.examples.CustomRectangle({
position: { x: x - rectWidth / 2, y: y - rectHeight / 2 },
size: { width: rectWidth, height: rectHeight },
attrs: {
text: { textWrap: { width: rectWidth * 0.95, height: 20, ellipsis: true, text: 'Datastore' } }
}
})
}
}
Now my understanding is, that if I require the JointJs module at the beginning of the script, and define a custom shape under it, that it would appear in the module and if needed later (in the factory) I could still access it over the same variable. But instead I get the following error:
Uncaught TypeError: Cannot read property 'CustomRectangle' of
undefined
I am also logging the module right after I have defined the custom shape, but it still doesn't show up.
Am I missing something about NodeJs or JointJs? Does anyone have an idea what the problem is? Any help would be appreciated.
I believe the issue is with how you're attaching it to joint.
Try this:
joint.shapes.examples.CustomRectangle = joint.shapes.standard.Rectangle.define('examples.CustomRectangle', {
attrs: {
body: {
refWidth: '100%',
refHeight: '100%',
strokeWidth: 5,
stroke: '#000000',
strokeDasharray: rectWidth + ',' + rectHeight,
fill: 'white'
},
label: {
textVerticalAnchor: 'middle',
textAnchor: 'middle',
refX: '50%',
refY: '50%',
fontSize: 14,
fill: '#333333'
}
}
});
Despite what the docs (https://resources.jointjs.com/tutorial/custom-elements) strongly imply, define() doesn't attach it to joint.

KonvaJS - How to add shape with button trigger?

Sorry for bad grammar-
i have a problem about how to add shape with button trigger.
but isn't working
here my code :
HTML
<button id="btnCreateRectangle" class="btn-primary-blue">Button Text</button>
And here my js :
function addRectangle(layer) {
var scale = 1;
var rectangle = new Konva.Rect({
x: 12,
y: 12,
numPoints: 5,
innerRadius: 30,
outerRadius: 50,
fill: "#89b717",
opacity: 0.8,
draggable: true,
name: 'rect',
width: 128,
height: 50,
scale: {
x: scale,
y: scale
},
shadowColor: "black",
shadowBlur: 4,
shadowOffset: {
x: 5,
y: 5
},
shadowOpacity: 0.6,
// custom attribute
startScale: scale
});
layer.add(rectangle);
}
document
.getElementById('btnCreateRectangle')
.addEventListener('click', function () {
addRectangle(layer)
});
Im very pretty new in javasrcipt language ,
any suggest or answer will be appreciate
thanks
from the documentation of KonvaJS after adding the rect to layer, you should add that layer to stage https://konvajs.org/docs/overview.html
stage.add(layer);

Marker is not aligning in Gauge chart using hight chart

I am trying to implement a gauge chart using high chart from data -100 to +100, when I tried to set initial data > 50 means custom marker aligning on the gauge. But if data is < 50 (Ex: 20 ) means custom marker is not aligning on the gauge line. JSFiddleLink
I tried in many way but unable to acheive.
Highcharts.chart('container', {
chart: {
style: {
fontFamily: "FuturaPTCond",
fontSize: "16px"
},
type: "solidgauge",
events: {
load: function() {
var elementSVG;
var chart = this,
counter = 0,
drawCircle = setInterval(function() {
if (++counter >= 1000) {
clearInterval(drawCircle);
}
renderCircle(chart);
function renderCircle(chart) {
let chartData = chart.userOptions.series[0].data[0];
let color =
chartData < -21
? "#DC143C"
: chartData > -21 && chartData < 21
? "#FF4500"
: chartData > 21 && chartData < 51
? "#FFFF00"
: chartData > 51 && chartData < 71
? "#00BFFF"
: chartData > 71 && chartData < 91
? "#ADFF2F"
: "#FF1493";
var series = chart.series[0],
pathDivided = series.points[0].graphic.attr("d").split(" "),
pathElemArr = [];
pathDivided.forEach(function(el, inx) {
if (el === "L") {
pathElemArr.push(parseFloat(pathDivided[inx + 1]));
pathElemArr.push(parseFloat(pathDivided[inx + 2]));
}
});
if (elementSVG) {
elementSVG.destroy();
}
document.getElementById(
"BackgroundColor"
).style.backgroundColor = "#fff";
elementSVG = chart.renderer
.circle(pathElemArr[0] + 11.25, pathElemArr[1], 10)
.attr({
fill: "#fff",
stroke: color,
width: "30px",
"stroke-width": 8,
zIndex: 10,
startAngle: -90,
endAngle: 90
})
.add();
}
}, 1);
$(".highcharts-axis-title").attr("x", 600.5);
$(".highcharts-axis-title").attr("y", 395.25);
$(".highcharts-credits").attr("x", 725);
},
redraw: function() {
$(".highcharts-axis-title").attr("x", 600.5);
$(".highcharts-axis-title").attr("y", 395.25);
$(".highcharts-credits").attr("x", 725);
}
}
},
title: null,
pane: {
center: ["50%", "85%"],
size: "98%",
startAngle: -90,
endAngle: 90,
background: {
backgroundColor: "#ffff",
innerRadius: "0%",
outerRadius: "0%"
},
shape: "arc"
},
// the value axis
yAxis: {
lineWidth: 0,
tickWidth: 0,
min: -100,
max: 100,
title: {
text: "<p style='font-size: 20px; font-weight: bold'>Last 30 Days</p>",
style: {
color: "grey"
}
},
tickPositions: [-100, -20, 20, 50, 70, 90, 100],
minorTickInterval: 0,
tickAmount: 0,
plotBands: [
{
from: -100,
to: -23,
borderWidth: 5,
borderColor: "#DC143C",
color: "#DC143C",
outerRadius: "95%"
},
{
from: -20,
to: 18,
borderWidth: 5,
borderColor: "#FF4500",
color: "#FF4500",
outerRadius: "95%"
},
{
from: 21,
to: 48,
borderWidth: 5,
borderColor: "#FFFF00",
color: "#FFFF00",
outerRadius: "95%"
},
{
from: 51,
to: 68,
borderWidth: 5,
borderColor: "#00BFFF",
color: "#00BFFF",
outerRadius: "95%"
},
{
from: 71,
to: 88,
borderWidth: 5,
borderColor: "#ADFF2F",
color: "#ADFF2F",
outerRadius: "95%"
},
{
from: 91,
to: 100,
borderWidth: 5,
borderColor: "#FF1493",
color: "#FF1493",
outerRadius: "95%"
}
],
labels: {
enabled: true,
distance: 10,
rotation: 0,
format: "<span style='fill:#00000; font-size: 16px'>{value}</span>"
}
},
plotOptions: {
solidgauge: {
borderColor: "#009CE8",
borderWidth: 0,
radius: 90,
innerRadius: "90%",
dataLabels: {
enabled: true,
y: 5,
borderWidth: 0,
useHTML: true,
format:
'<div id="BackgroundColor" style="Width: 50px;text-align:center"><span style="font-size:70px;color: #000000; margin-left: -20px">{y}</span></div>'
}
}
},
series: [
{
name: "Speed",
data: [20],
animation: {
duration: 1500
}
}
]
});
I think something is wrong with how you are parsing the d attribute of the path?
Also, when you enter 100 as the data the circle is a bit short of 100?
And when you have data as 0 or 100, the circle is on the faint blue line, but otherwise, at zero (in the middle) it is off from the faint blue line:
This suggests to me that the x-position is correct but the y-position is offset negative direction (towards the top of the svg) and needs to be pushed down (translate positive y)
I changed the color to black just to see it better and then you can see with transform: 'translate(0 10)' the black circle falls perfectly on the light blue line (and also when the data is 100 it lines up with 100 correctly):
Finally, with all inner and outer radius adjusted etc. to centre it:
Note the following style is added to remove the light blue line from the chart:
<style>
.highcharts-point{
opacity: 0;
}
</style>
Probably, this translation(0 10) is needed because of this element (and its translation):
<g data-z-index="0.1" class="highcharts-series highcharts-series-0 highcharts-solidgauge-series highcharts-tracker" transform="translate(10,10) scale(1 1)" clip-path="url(#highcharts-fh3kcab-2-)"/>
Full working demo: https://jsfiddle.net/alexander_L/1yewj7r5/26/

Animate "fillLinearGradientColorStops" of a shape

How can I animate fillLinearGradientColorStops of a KineticJS Rect? I tried using a tween but surely it doesn't work.
The rectangle:
var rect = new Kinetic.Rect({
x: 20,
y: 20,
width: 100,
height: 100,
fillLinearGradientStartPoint: { x: -50, y: -50 },
fillLinearGradientEndPoint: { x: 50, y: 50 },
fillLinearGradientColorStops: [0, 'red', 1, 'yellow']
});
The tween:
var tween = new Kinetic.Tween({
node: rect,
duration: 2,
easing: Kinetic.Easings.Linear,
fillLinearGradientColorStops: [0, 'black', 1, 'green']
});
tween.play();
Please see the fiddle http://jsfiddle.net/ZdCmS/. Is it not possible?
From there: https://github.com/ericdrowell/KineticJS/issues/901
You can use an external tweening library, like GreenSock (http://www.greensock.com/gsap-js/) with it's ColorProps plugin (http://api.greensock.com/js/com/greensock/plugins/ColorPropsPlugin.html) to tween colors and then apply them to the Kinetic shape on each frame update: http://jsfiddle.net/ZH2AS/2/
No plans for direct support of tweening color stops on a gradient fill.
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var linearGradPentagon = new Kinetic.RegularPolygon({
x: 150,
y: stage.height() / 2,
sides: 5,
radius: 70,
fillLinearGradientStartPoint: {
x: -50,
y: -50
},
fillLinearGradientEndPoint: {
x: 50,
y: 50
},
fillLinearGradientColorStops: [0, 'white', 1, 'black'],
stroke: 'black',
strokeWidth: 4,
draggable: true
});
layer.add(linearGradPentagon);
stage.add(layer);
//activate ColorPropsPlugin
TweenPlugin.activate([ColorPropsPlugin]);
//object to store color values
var tmpColors = {
color0: 'white',
color1: 'black'
};
//tween the color values in tmpColors
TweenMax.to(tmpColors, 5, {
colorProps: {
color0: 'black',
color1: 'red'
},
yoyo: true,
repeat: 5,
ease:Linear.easeNone,
onUpdate: applyProps
});
function applyProps() {
linearGradPentagon.setAttrs({
fillLinearGradientColorStops: [0, tmpColors.color0, 1, tmpColors.color1]
});
layer.batchDraw();
}

Categories

Resources