How to put a text inside a rect using konva.js? - javascript

I have a project with some rects and I need to put text inside them. Is there a Konva class that does this?
I have tried using Konva.group (), label ...
This was my last attempt, at the beginning the text stands as it should but when moving the Rect the position is not updated.
var rect = new Konva.Rect({
x: 20,
y: 60,
stroke: '#123456',
strokeWidth: 5,
fill: '#ddd',
width: 600,
height: 450,
shadowColor: 'black',
shadowBlur: 10,
shadowOffset: [10, 10],
shadowOpacity: 0.2,
cornerRadius: 10,
draggable: true,
})
var complexText = new Konva.Text({
x: ((rect.attrs.width + rect.attrs.x) - 300)/2 ,
y: ((rect.attrs.height + rect.attrs.y))/2,
text:
"COMPLEX TEXT\n\nAll the world's a stage, and all the men and women merely players. They have their exits and their entrances.",
fontSize: 18,
fontFamily: 'Calibri',
fill: '#555',
width: 300,
height:300,
align: 'center',
draggable: true,
});

var width = window.innerWidth;
var height = window.innerHeight;
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
draggable: true
});
var rectangleLayer = new Konva.Layer();
function spawnRectangle(angle){
var rectangle = new Konva.Group({
x: 25,
y: 25,
width: 130,
height: 25,
rotation: angle,
draggable: true,
});
rectangle.add(new Konva.Rect({
width: 130,
height: 25,
fill: 'lightblue'
}));
rectangle.add(new Konva.Text({
text:'123',
fontSize: 18,
fontFamily: 'Calibri',
fill: '#000',
width: 130,
padding: 5,
align: 'center'
}));
rectangleLayer.add(rectangle);
stage.add(rectangleLayer);
}
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #D3D3D3;
background-size: cover;
}
#desc {
position : absolute;
top: 5px;
left: 5px;
}
<script src="https://unpkg.com/konva#4.0.18/konva.min.js"></script>
<body>
<div id="container"></div>
<div id="desc">
<button onclick="spawnRectangle(0)">spawn rectangle</button>
<button onclick="spawnRectangle(90)">spawn rotated rectangle</button>
</div>
</body>

Your options are:
Use Konva.Label
Create a draggable group with rectangle and text inside
Create one custom shape. Draw rectangle and text inside sceneFunc

Related

How to trigger click on canvas object and DOM element that is placed on top of object at the same time?

I have some circles that can be added to a fabricjs canvas. Each circle is an object, while outside my javascript code I have a DOM element, that looks like this:
<span id="cirkel1" class="carttip inlineflexmenu" style="border-radius:100%;width: 25px;height:25px;z-index:9999999;position:absolute;cursor:pointer;">
<div class="tooltipcontent darktext tooltippadding" style="position:relative;">
Testtest
</div>
</span>
This element triggers a tooltip with Tippjs (a js tooltip package), that has the following code (don't mind the each loop, I should also mention below code is outside the canvas function):
$( "#cirkel1" ).each(function( i ) {
tippy(this, {
theme: 'blue',
trigger: 'click',
allowHTML: true,
placement: 'right',
animation: 'scale-subtle',
interactive: true,
content: function (reference) {
return reference.querySelector('.tooltipcontent');
}
});
});
Inside my function where I declare everything for the canvas, I have the following code to place the DOM element on top of the canvas object:
fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
return {
left: object.left + this._offset.left,
top: object.top + this._offset.top
};
}
var cirkel1tooltip = document.getElementById('cirkel1'),
btnWidth = 40,
btnHeight = 40;
function positionBtn(obj) {
var absCoords = canvas.getAbsoluteCoords(obj);
cirkel1tooltip.style.left = (absCoords.left - btnWidth / 10) + 'px';
cirkel1tooltip.style.top = (absCoords.top - btnHeight / 10) + 'px';
}
This works, and the tooltip shows when clicked, but in my canvas function I also have a click function which toggles an image for a specific circle when clicked. I need both to trigger at the same time when the circle is clicked, now when I click a circle, the image appears, but only after I click a second time, the tooltip appears too, not at the same first click.
Removing the image by clicking a second time also doesn't work untill I click on another circle and then click back on the previously clicked circle.
The strange thing is, when I remove one of the two functions (tooltip click, or image toggle click) it works instant, but together only the image toggle works right away but the tooltip only after a second click. Why is that?
The entire code can be seen here (click the small circles to test): https://codepen.io/twan2020/pen/jOVaWMm
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<base href="//printzelf.nl/new/">
<title>Image test</title>
<link rel="stylesheet" href="https://unpkg.com/tippy.js#6/animations/scale-subtle.css"/>
<link rel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
</head>
<body>
<style media="screen">
.tippy-box {
width: 100%!important;
text-align: center;
background-color: #fff!important;
color: #fff!important;
box-shadow: 3px 2px 15px 6px rgb(0 0 0 / 10%);
}
.darktext {
color: #383838;
font-family: Panton;
font-size: 15px;
}
.tooltippadding {
padding: 15px;
}
body .tippy-arrow {
color: #fff!important;
}
</style>
<img id="background" src="https://static01.nyt.com/images/2019/05/29/realestate/00skyline-south4/88ce0191bfc249b6aae1b472158cccc4-superJumbo.jpg" alt="" style="display:none;">
<div class="canvas-container" style="width: 600px; height: 500px; position: relative; user-select: none;">
<canvas id="c" width="600" height="500" class="lower-canvas" style="border:1px solid red;position: absolute; width: 600px; height: 500px; left: 0px; top: 0px; touch-action: none; user-select: none;"></canvas>
</div>
</body>
<span id="cirkel1" class="carttip inlineflexmenu" style="border-radius:100%;width: 25px;height:25px;z-index:9999999;position:absolute;cursor:pointer;">
<div class="tooltipcontent darktext tooltippadding" style="position:relative;">
Testtest
</div>
</span>
<!-- Popper JS -->
<script src="assets/js/popper.min.js"></script>
<script src="https://unpkg.com/tippy.js#6"></script>
<script type="text/javascript" src="assets/js/fabric.js"></script>
<script type="text/javascript">
(function() {
var myImg = document.querySelector("#background");
var realWidth = myImg.naturalWidth;
var realHeight = myImg.naturalHeight;
var source = document.getElementById('background').src;
var canvas = new fabric.Canvas('c');
canvas.hoverCursor = 'pointer';
canvas.selection = false;
canvas.setDimensions({ width: realWidth, height: realHeight });
var img = new Image();
// use a load callback to add image to canvas.
img.src = 'https://static01.nyt.com/images/2019/05/29/realestate/00skyline-south4/88ce0191bfc249b6aae1b472158cccc4-superJumbo.jpg';
canvas.setBackgroundImage(source, canvas.renderAll.bind(canvas), {
backgroundImageOpacity: 0.5,
backgroundImageStretch: false
});
const hotspots = [
{
top: 140,
left: 230,
radius: 10,
fill: '#009fe3',
id: 'cirkel1',
hoverCursor: 'pointer',
selectable: false,
imgtop: 200,
imgleft: 300,
imgheight: 200,
imgwidth: 200,
tooltipid: 'cirkel1',
imgUrl: 'https://printzelf.nl/new/assets/images/logo_gewoon.png'
},
{
top: 240,
left: 530,
radius: 10,
fill: '#009fe3',
id: 'cirkel2',
hoverCursor: 'pointer',
selectable: false,
imgtop: 200,
imgleft: 700,
imgheight: 200,
imgwidth: 200,
imgUrl: 'https://i1.wp.com/nypost.com/wp-content/uploads/sites/2/2020/04/pugs-coronavirus.jpg'
},
{
top: 240,
left: 730,
radius: 10,
fill: '#009fe3',
id: 'cirkel2',
hoverCursor: 'pointer',
selectable: false,
imgtop: 200,
imgleft: 800,
imgheight: 200,
imgwidth: 200,
imgUrl: 'https://i.guim.co.uk/img/media/fe1e34da640c5c56ed16f76ce6f994fa9343d09d/0_174_3408_2046/master/3408.jpg?width=1200&height=900&quality=85&auto=format&fit=crop&s=0d3f33fb6aa6e0154b7713a00454c83d'
}
];
const loadedImages = [];
for (let [idx, props] of hotspots.entries()) {
let c = new fabric.Circle(props);
c.class = 'hotspot';
c.name = 'hotspot-' + idx;
canvas.add(c);
}
fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
return {
left: object.left + this._offset.left,
top: object.top + this._offset.top
};
}
var cirkel1tooltip = document.getElementById('cirkel1'),
btnWidth = 40,
btnHeight = 40;
function positionBtn(obj) {
var absCoords = canvas.getAbsoluteCoords(obj);
cirkel1tooltip.style.left = (absCoords.left - btnWidth / 10) + 'px';
cirkel1tooltip.style.top = (absCoords.top - btnHeight / 10) + 'px';
}
for (const ho of canvas.getObjects()) {
// check for 'hotspot' class
if (ho.class && ho.class === 'hotspot') {
ho.on('mousedown', () => {
// check if image was previously loaded
if (loadedImages.indexOf(ho.name) < 0) {
// image is not in the array
// so it needs to be loaded
// prepare the image properties
let imgProps = {
width: ho.imgwidth,
height: ho.imgheight,
left: ho.imgleft,
top: ho.imgtop,
scaleX: .25,
scaleY: .25,
selectable: false,
id: 'img-' + ho.name,
hoverCursor: "default"
};
var printzelfImg = new Image();
printzelfImg.onload = function (img) {
var printzelf = new fabric.Image(printzelfImg, imgProps);
canvas.add(printzelf);
};
printzelfImg.src = ho.imgUrl;
// update the `loadedImages` array
loadedImages.push(ho.name);
} else {
// image was previously loaded
for (const o of canvas.getObjects()) {
// find the correct image on the canvas
if (o.id && o.id === 'img-' + ho.name) {
// toggle the visible property
o.visible = !o.visible;
break;
}
}
}
positionBtn(ho);
});
}
}
})();
$( "#cirkel1" ).each(function( i ) {
tippy(this, {
theme: 'blue',
trigger: 'click',
allowHTML: true,
placement: 'right',
animation: 'scale-subtle',
interactive: true,
content: function (reference) {
return reference.querySelector('.tooltipcontent');
}
});
});
</script>
</html>
Also, is it possible to attach different tooltips to each dot/circle?
The reason why it didn't work is that you have just 1 DIV hotspot and you move this hotspot on mousedown and expect it to trigger the onclick event afterward which doesn't work. The reason why it works on second click is that the hotspot it now there.
The solution is to have the same amount of DIV as you have hotspot. This allows you to have unique popup message. Currently it displays the same message for each hotspot.
There is an onShow(instance), and onHide(instance) for the tippy property which allows you to carryout extra functionality when these hotspot are clicked on. In your case you want to load images related to the selected hotspot. This eliminate having two events setup.
There was also a problem toggling images. I fixed this but I am not 100% certain it is working how you would like this to work.
Also you had HTML tags outside the <body> tag and HTML content aren't supposed to exist outside body.
I kept most of your original code as much as I can.
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<base href="//printzelf.nl/new/">
<title>Image test</title>
<link rel="stylesheet" href="https://unpkg.com/tippy.js#6/animations/scale-subtle.css"/>
<link rel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<style media="screen">
.tippy-box {
width: 100%!important;
text-align: center;
background-color: #fff!important;
color: #fff!important;
box-shadow: 3px 2px 15px 6px rgb(0 0 0 / 10%);
}
.darktext {
color: #383838;
font-family: Panton;
font-size: 15px;
}
.tooltippadding {
padding: 15px;
}
body .tippy-arrow {
color: #fff!important;
}
</style>
</head>
<body>
<img id="background" src="https://static01.nyt.com/images/2019/05/29/realestate/00skyline-south4/88ce0191bfc249b6aae1b472158cccc4-superJumbo.jpg" alt="" style="display:none;">
<div class="canvas-container" style="width: 600px; height: 500px; position: relative; user-select: none;">
<canvas id="c" width="600" height="500" class="lower-canvas" style="border:1px solid red;position: absolute; width: 600px; height: 500px; left: 0px; top: 0px; touch-action: none; user-select: none;"></canvas>
</div>
<span id="cirkel1" class="carttip inlineflexmenu" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontent1 tooltipcontent darktext tooltippadding" style="position:relative;">
Message 1
</div>
</span>
<span id="cirkel2" class="carttip inlineflexmenu" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontent2 tooltipcontent darktext tooltippadding" style="position:relative;">
Message 2
</div>
</span>
<span id="cirkel3" class="carttip inlineflexmenu" style="border-radius:100%;width: 25px;height:25px;position:absolute;cursor:pointer;">
<div class="tooltipcontent3 tooltipcontent darktext tooltippadding" style="position:relative;">
Message 3
</div>
</span>
<!-- Popper JS -->
<script src="assets/js/popper.min.js"></script>
<script src="https://unpkg.com/tippy.js#6"></script>
<script type="text/javascript" src="assets/js/fabric.js"></script>
<script type="text/javascript">
(function() {
var myImg = document.querySelector("#background");
var realWidth = myImg.naturalWidth;
var realHeight = myImg.naturalHeight;
var source = document.getElementById('background').src;
var canvas = new fabric.Canvas('c');
canvas.hoverCursor = 'pointer';
canvas.selection = false;
canvas.setDimensions({ width: realWidth, height: realHeight });
var img = new Image();
// use a load callback to add image to canvas.
img.src = 'https://static01.nyt.com/images/2019/05/29/realestate/00skyline-south4/88ce0191bfc249b6aae1b472158cccc4-superJumbo.jpg';
canvas.setBackgroundImage(source, canvas.renderAll.bind(canvas), {
backgroundImageOpacity: 0.5,
backgroundImageStretch: false
});
const hotspots = [
{
top: 140,
left: 230,
radius: 10,
fill: '#009fe3',
id: 'cirkel1',
hoverCursor: 'pointer',
selectable: false,
imgtop: 200,
imgleft: 300,
imgheight: 200,
imgwidth: 200,
tooltipid: 'cirkel1',
imgUrl: 'https://printzelf.nl/new/assets/images/logo_gewoon.png'
},
{
top: 240,
left: 530,
radius: 10,
fill: '#009fe3',
id: 'cirkel2',
hoverCursor: 'pointer',
selectable: false,
imgtop: 200,
imgleft: 700,
imgheight: 200,
imgwidth: 200,
imgUrl: 'https://i1.wp.com/nypost.com/wp-content/uploads/sites/2/2020/04/pugs-coronavirus.jpg'
},
{
top: 240,
left: 730,
radius: 10,
fill: '#009fe3',
id: 'cirkel2',
hoverCursor: 'pointer',
selectable: false,
imgtop: 200,
imgleft: 800,
imgheight: 200,
imgwidth: 200,
imgUrl: 'https://i.guim.co.uk/img/media/fe1e34da640c5c56ed16f76ce6f994fa9343d09d/0_174_3408_2046/master/3408.jpg?width=1200&height=900&quality=85&auto=format&fit=crop&s=0d3f33fb6aa6e0154b7713a00454c83d'
}
];
const loadedImages = [];
for (let [idx, props] of hotspots.entries()) {
let c = new fabric.Circle(props);
c.class = 'hotspot';
c.name = 'hotspot-' + idx;
canvas.add(c);
}
fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
return {
left: object.left + this._offset.left,
top: object.top + this._offset.top
};
}
var cirkel1tooltip = document.getElementById('cirkel1'),
btnWidth = 40,
btnHeight = 40;
function positionBtn(obj, index) {
var absCoords = canvas.getAbsoluteCoords(obj);
var element = document.getElementById('cirkel'+index);
element.style.left = (absCoords.left - btnWidth / 10) + 'px';
element.style.top = (absCoords.top - btnHeight / 10) + 'px';
}
canvas.getObjects().forEach(function(ho, index) {
positionBtn(ho, index + 1);
});
$( ".carttip" ).each(function( i ) {
tippy(this, {
theme: 'blue',
trigger: 'click',
allowHTML: true,
placement: 'right',
animation: 'scale-subtle',
interactive: true,
onShow(instance) {
canvas.getObjects().forEach(function(ho, index) {
if (ho.class && ho.class === 'hotspot') {
if (instance.id == index + 1) {
// check if image was previously loaded
if (loadedImages.indexOf(ho.name) < 0) {
// image is not in the array
// so it needs to be loaded
// prepare the image properties
let imgProps = {
width: ho.imgwidth,
height: ho.imgheight,
left: ho.imgleft,
top: ho.imgtop,
scaleX: .25,
scaleY: .25,
selectable: false,
id: 'img-' + ho.name,
hoverCursor: "default",
};
var printzelfImg = new Image();
printzelfImg.onload = function (img) {
var printzelf = new fabric.Image(printzelfImg, imgProps);
printzelf.trippyHotspotImage = true;
canvas.add(printzelf);
};
printzelfImg.src = ho.imgUrl;
// update the `loadedImages` array
loadedImages.push(ho.name);
} else {
for (const o of canvas.getObjects()) {
if (o.id && o.id === 'img-' + ho.name) {
o.visible = true;
break;
}
}
canvas.renderAll();
}
}
}
});
},
onHide(instance) {
for (const o of canvas.getObjects()) {
if (o.trippyHotspotImage) {
o.visible = false;
}
}
canvas.renderAll();
},
content: function (reference) {
return reference.querySelector('.tooltipcontent' + (i + 1));
}
});
});
})();
</script>
</body>
</html>
It looks like the first time the click event isn't fired right after the mousedown one the first time. The framework you use seems to prevent this because a process (by the listener) is performed.
(It may be related to event propagation but at this time I still didn't find out how to prevent a click event to be fired after a mouseup.)
What I would call a workaround: to display the tool tip in the same click, i.e. a mousedown event followed by a mouseup one, you can set mouseup value for the trigger property, which displays the tool tip:
$( "#cirkel1" ).each(function( i ) {
tippy(this, {
theme: 'blue',
trigger: 'mouseup', /* <-- here */
allowHTML: true,
placement: 'right',
animation: 'scale-subtle',
interactive: true,
content: function (reference) {
return reference.querySelector('.tooltipcontent');
}
});
The mouseup event will be fired if the mousedown occurred on the circle.
Working snippet.
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<base href="//printzelf.nl/new/">
<title>Image test</title>
<link rel="stylesheet" href="https://unpkg.com/tippy.js#6/animations/scale-subtle.css"/>
<link rel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
</head>
<body>
<style media="screen">
.tippy-box {
width: 100%!important;
text-align: center;
background-color: #fff!important;
color: #fff!important;
box-shadow: 3px 2px 15px 6px rgb(0 0 0 / 10%);
}
.darktext {
color: #383838;
font-family: Panton;
font-size: 15px;
}
.tooltippadding {
padding: 15px;
}
body .tippy-arrow {
color: #fff!important;
}
</style>
<img id="background" src="https://static01.nyt.com/images/2019/05/29/realestate/00skyline-south4/88ce0191bfc249b6aae1b472158cccc4-superJumbo.jpg" alt="" style="display:none;">
<div class="canvas-container" style="width: 600px; height: 500px; position: relative; user-select: none;">
<canvas id="c" width="600" height="500" class="lower-canvas" style="border:1px solid red;position: absolute; width: 600px; height: 500px; left: 0px; top: 0px; touch-action: none; user-select: none;"></canvas>
</div>
</body>
<span id="cirkel1" class="carttip inlineflexmenu" style="border-radius:100%;width: 25px;height:25px;z-index:9999999;position:absolute;cursor:pointer;">
<div class="tooltipcontent darktext tooltippadding" style="position:relative;">
Testtest
</div>
</span>
<!-- Popper JS -->
<script src="assets/js/popper.min.js"></script>
<script src="https://unpkg.com/tippy.js#6"></script>
<script type="text/javascript" src="assets/js/fabric.js"></script>
<script type="text/javascript">
(function() {
var myImg = document.querySelector("#background");
var realWidth = myImg.naturalWidth;
var realHeight = myImg.naturalHeight;
var source = document.getElementById('background').src;
var canvas = new fabric.Canvas('c');
canvas.hoverCursor = 'pointer';
canvas.selection = false;
canvas.setDimensions({ width: realWidth, height: realHeight });
var img = new Image();
// use a load callback to add image to canvas.
img.src = 'https://static01.nyt.com/images/2019/05/29/realestate/00skyline-south4/88ce0191bfc249b6aae1b472158cccc4-superJumbo.jpg';
canvas.setBackgroundImage(source, canvas.renderAll.bind(canvas), {
backgroundImageOpacity: 0.5,
backgroundImageStretch: false
});
const hotspots = [
{
top: 140,
left: 230,
radius: 10,
fill: '#009fe3',
id: 'cirkel1',
hoverCursor: 'pointer',
selectable: false,
imgtop: 200,
imgleft: 300,
imgheight: 200,
imgwidth: 200,
tooltipid: 'cirkel1',
imgUrl: 'https://printzelf.nl/new/assets/images/logo_gewoon.png'
},
{
top: 240,
left: 530,
radius: 10,
fill: '#009fe3',
id: 'cirkel2',
hoverCursor: 'pointer',
selectable: false,
imgtop: 200,
imgleft: 700,
imgheight: 200,
imgwidth: 200,
imgUrl: 'https://i1.wp.com/nypost.com/wp-content/uploads/sites/2/2020/04/pugs-coronavirus.jpg'
},
{
top: 240,
left: 730,
radius: 10,
fill: '#009fe3',
id: 'cirkel2',
hoverCursor: 'pointer',
selectable: false,
imgtop: 200,
imgleft: 800,
imgheight: 200,
imgwidth: 200,
imgUrl: 'https://i.guim.co.uk/img/media/fe1e34da640c5c56ed16f76ce6f994fa9343d09d/0_174_3408_2046/master/3408.jpg?width=1200&height=900&quality=85&auto=format&fit=crop&s=0d3f33fb6aa6e0154b7713a00454c83d'
}
];
const loadedImages = [];
for (let [idx, props] of hotspots.entries()) {
let c = new fabric.Circle(props);
c.class = 'hotspot';
c.name = 'hotspot-' + idx;
canvas.add(c);
}
fabric.Canvas.prototype.getAbsoluteCoords = function(object) {
return {
left: object.left + this._offset.left,
top: object.top + this._offset.top
};
}
var cirkel1tooltip = document.getElementById('cirkel1'),
btnWidth = 40,
btnHeight = 40;
function positionBtn(obj) {
var absCoords = canvas.getAbsoluteCoords(obj);
cirkel1tooltip.style.left = (absCoords.left - btnWidth / 10) + 'px';
cirkel1tooltip.style.top = (absCoords.top - btnHeight / 10) + 'px';
}
for (const ho of canvas.getObjects()) {
// check for 'hotspot' class
if (ho.class && ho.class === 'hotspot') {
ho.on('mousedown', () => {
// check if image was previously loaded
if (loadedImages.indexOf(ho.name) < 0) {
// image is not in the array
// so it needs to be loaded
// prepare the image properties
let imgProps = {
width: ho.imgwidth,
height: ho.imgheight,
left: ho.imgleft,
top: ho.imgtop,
scaleX: .25,
scaleY: .25,
selectable: false,
id: 'img-' + ho.name,
hoverCursor: "default"
};
var printzelfImg = new Image();
printzelfImg.onload = function (img) {
var printzelf = new fabric.Image(printzelfImg, imgProps);
canvas.add(printzelf);
};
printzelfImg.src = ho.imgUrl;
// update the `loadedImages` array
loadedImages.push(ho.name);
} else {
// image was previously loaded
for (const o of canvas.getObjects()) {
// find the correct image on the canvas
if (o.id && o.id === 'img-' + ho.name) {
// toggle the visible property
o.visible = !o.visible;
break;
}
}
}
positionBtn(ho);
});
}
}
})();
$( "#cirkel1" ).each(function( i ) {
tippy(this, {
theme: 'blue',
trigger: 'mouseup',
allowHTML: true,
placement: 'right',
animation: 'scale-subtle',
interactive: true,
content: function (reference) {
return reference.querySelector('.tooltipcontent');
}
});
});
</script>
</html>

move a horizontal line to the center in StyledSheets

I have drawn a horizontal line like this. However, it appears towards the left side of the screen. I don't want to increase the width. How else can I move it to the center? I tried wrapping it with another view along with alignContent: 'center' etc but it didn't work for me.
<View style={styles.horizontalLine}></View>
horizontalLine: {
marginTop: 25,
width: '80%',
height: 1,
//alignContent: 'center',
//width: 1,
backgroundColor: '#E0E0E0',
},
Add an alignSelf:'center' like below
horizontalLine: {
marginTop: 25,
width: '80%',
height: 1,
//alignContent: 'center',
//width: 1,
alignSelf: 'center',
backgroundColor: '#E0E0E0',
}
You can give horizontal margin: auto
horizontalLine: {
// ...
marginLeft: 'auto',
marginRight: 'auto',
// ...
},
Try this...
horizontalLine: {
margin: 'auto',
marginTop: 25,
width: '80%',
height: 1,
backgroundColor: '#E0E0E0',
}

Scale rectangle object from middle – fabricjs

I have a rectangle object on fabricjs canvas. Now, when I try to scale the rectangle it always scales from a fixed corner and only expands to the direction where the mouse is. What I want is, when I scale it should scale from center and expand either side. I tried setting originX and originY but that didn’t work. Can anyone help me on this? Thanks!
var rect = new fabric.Rect({
top: 150,
left: 150,
width: 100,
height: 100,
fill: 'black',
originX: 'center',
originY: 'center',
});
You need to set centeredScaling property to true for the rectangle object to make its' scale origin to center ...
var canvas = new fabric.Canvas('c');
var rect = new fabric.Rect({
top: 100,
left: 100,
width: 50,
height: 50,
fill: 'black',
originX: 'center',
originY: 'center',
centeredScaling: true
});
canvas.add(rect).renderAll();
canvas{border: 1px solid #ccc}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.11/fabric.min.js"></script>
<canvas id="c" width="200" height="200"></canvas>

jQuery circle progress bar and percentage text animation when screen visible

I'm a novice in jQuery and I'm using jquery-circle-progress plugin by kottenator. I've four circles and I want to animate its bar and percentage text when it's area visible on the screen. Like most of websites make the effect.
Could anyone please help me to make that effect with a little explanation? Thanks in advance, Dear. My fiddle
HTML:
<section class="firstDiv"></section>
<section class="secondDiv"></section>
<div class="thirdDiv">
<div id="circle1">
<span class="rate">85%</span>
</div>
<div id="circle2">
<span class="rate">90%</span>
</div>
<div id="circle3">
<span class="rate">80%</span>
</div>
<div id="circle4">
<span class="rate">70%</span>
</div>
</div>
CSS:
section{ height: 700px; overflow: hidden;}
.firstDiv{ background: blue;}
.secondDiv{ background: yellow;}
.thirdDiv div{
float: left;
width: 25%;
overflow: hidden;
margin: 50px 0;
position: relative;
}
.rate{
position: absolute;
top: 40%;
left: 25%;
}
JS:
$('#circle1').circleProgress({
value: 0.85,
size: 100,
fill: {
gradient: [ "#FD0000" , "#FD7300", "#FDBD00"]
}
});
$('#circle2').circleProgress({
value: 0.90,
size: 100,
fill: {
gradient: ["#00B050", "#00CA00", "#9EEC00"]
}
});
$('#circle3').circleProgress({
value: 0.80,
size: 100,
fill: {
gradient: ["#FDFD00", "#FDE700", "#CDF500"]
}
});
$('#circle4').circleProgress({
value: 0.70,
size: 100,
fill: {
gradient: ["#123FAA", "#3914AE", "#0B63A3"]
}
});
My fiddle
Ok, It was a pretty good experience. I've solved the problem by using jquery.appear plugin. I've insert my full code into this portion of code:
var el = $('.circle'),
inited = false;
el.appear({ force_process: true });
el.on('appear', function() {
if (!inited) {
el.circleProgress({ value: 0.7 });
inited = true;
}
});
It's a nice plugin, which execute the code when the div(in my case .thirdDiv) on screen. My full JS code is below:
var el = $('.thirdDiv'),
inited = false;
el.appear({ force_process: true });
el.on('appear', function() {
if (!inited) {
$("#circle1").circleProgress({
value: 0.7,
size: 100,
fill: {
gradient: [ "#FD0000" , "#FD7300", "#FDBD00"]
}
});
$("#circle2").circleProgress({
value: 0.90,
size: 100,
fill: {
gradient: ["#00B050", "#00CA00", "#9EEC00"]
}
});
$("#circle3").circleProgress({
value: 0.80,
size: 100,
fill: {
gradient: ["#FDFD00", "#FDE700", "#CDF500"]
}
});
$("#circle4").circleProgress({
value: 0.70,
size: 100,
fill: {
gradient: ["#123FAA", "#3914AE", "#0B63A3"]
}
});
inited = true;
}
});
Thanks everybody :)

Justgage.js Change Title,Value,Label font-size

I am trying the reduce the font-size using [titleFontSize: 12..] and various combinations. but not working.
same i used for [valueFontSize: ..] & [labelFontSize: ..]
How can i change the font-size of Title,Value & Labels?
Code:
<script src="js/raphael-2.1.4.min.js"></script>
<script src="js/justgage.js">
<script type="text/javascript">
var gD = new JustGage({
id: "jgDownload",
value: 67,
decimals: 2,
min: 0,
max: 1000,
title: "Download",
titleFontSize: 12,
titlePosition: "below",
titleFontColor: "red",
titleFontFamily: "Georgia",
titlePosition: "below",
valueFontColor: "blue",
valueFontFamily: "Georgia"
label: "Mbps",
lableFontSize: "10px",
width: 300,
height: 200,
relativeGaugeSize: true,
levelColors: [
"#E63454",
"#AC001F",
"#F6AD37",
"#B87200",
"#24A081",
"#007759",
"#026071",
"#015C71"
],
pointer: true,
counter: true,
});
</script>
var gD = new JustGage({
id: "jgDownload",
value: 67,
decimals: 2,
min: 0,
max: 1000,
title: "Download",
titleFontSize: "5px",
titlePosition: "below",
valueFontFamily: "Georgia",
valueFontSize: "5px",
label: "Mbps",
width: 300,
height: 200,
relativeGaugeSize: true,
levelColors: [
"#E63454",
"#AC001F",
"#F6AD37",
"#B87200",
"#24A081",
"#007759",
"#026071",
"#015C71"
],
pointer: true,
counter: true,
});
#divDownloadOuter {
width: 50%;
clear: both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.4/raphael-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/justgage/1.2.2/justgage.js"></script>
<div id="divDownloadOuter">
<div id="jgDownload"></div>
</div>
JSFiddle: Link
Try with titleMinFontSize. It will work.
titleMinFontSize: 20,
Check this link for other attributes.
Solution using CSS:
/* Title */
#jgDownload text:nth-child(6) tspan{
font-size: 0.8em !important;
}
/* Value */
#jgDownload text:nth-child(7) tspan{
font-size: 0.5em !important;
}
/* Label */
#jgDownload text:nth-child(8) tspan, #jgDownload text:nth-child(9) tspan, #jgDownload text:nth-child(10) tspan{
font-size: 0.9em !important;
}
Check this link with Example: https://jsfiddle.net/amitshahc/gf0gm69j/5/
To get it working with justGage v1.2.2 I used the following:
/* Value */
#jgDownload > svg:nth-child(1) > text:nth-child(6) {
font-size: 0.8em !important;
}
(the 'text:nth-child' value dictates which element to change, i.e. text:nth-child(8) and text:nth-child(9) represents the labels)
Be gentle on me as this is my first post!

Categories

Resources