FabricJS modify custom properties - javascript

I am using the FabricJS graphics library and have added an additional property (name) to a fabric.Rect object. All well and good and it serializes out to JSON correctly.
I am struggling though with the code needed to allow me to subsequently change the customer property once set i.e. to change 'some name' to something else. It is driving me a bit crazy.
Any additional help really appreciated.
Thanks,
Shaun
const o = new fabric.Rect({
width: width,
height: height,
fill: tableFill,
stroke: tableStroke,
strokeWidth: 2,
shadow: tableShadow,
originX: "center",
originY: "center",
centeredRotation: true,
snapAngle: 45,
selectable: true,
strokeUniform: true
});
o.toObject = (function(toObject) {
return function(propertiesToInclude) {
return fabric.util.object.extend(toObject.call(this, propertiesToInclude), {
name: 'some name'
});
};
})(o.toObject);
console.log(o.toObject().name)

So, basically run this code to allow any additional properties to be serialised to and from JSON. In this example a property called name is added.
const originalToObject = fabric.Object.prototype.toObject;
const myAdditional = ['name'];
fabric.Object.prototype.toObject = function (additionalProperties) {
return originalToObject.call(this, myAdditional.concat(additionalProperties));
}
Then create a new Fabric object and set or get the additional properties as needed...
const o = new fabric.Rect({
width: width,
height: height,
fill: tableFill,
stroke: tableStroke,
strokeWidth: 2,
shadow: tableShadow,
originX: "center",
originY: "center",
centeredRotation: true,
snapAngle: 45,
selectable: true,
strokeUniform: true
});
o.name = 'Fred'
console.log(o.toJSON())

Related

Konva setAttr not a function error for children

I'm using Konva and trying to change the fill color of a tag using the setAttrs, however I keep getting an error "setAttrs is not a function" I'm trying to start by getting a child of the label, and setting the attribute of that. Any thought's on what I could be doing wrong?
// Add labels for each IO
var IO = new Konva.Label({
x: 10,
y: 10,
name: "Tag 1",
});
IO.add(
new Konva.Tag({
fill: '#C1EFF5',
stroke: '#555',
strokeWidth: 2,
})
);
IO.add(
new Konva.Text({
text: "TestText",
fontFamily: 'Calibri',
fontSize: 12,
padding: 5,
fill: 'black',
})
);
// Add listening Events such as clicking
IO.on('click', function () {
// get only Tag
var tagsClicked = this.getChildren(function(node){
return node.getClassName() === 'Tag';
});
tagsClicked.setAttrs({
fill: 'red'
});
});
// Add the input to the group for display
group.add(IO);

fabricjs label on hover

I try to add label when user hover element:
var rect = new fabric.Rect({
originX: 'top',
originY: 'top',
width: 150,
height: 120,
fill: 'rgba(255,0,0,0.5)',
transparentCorners: true
});
var text = new fabric.Text('hello world', {
fontSize: 30,
originX: 'top',
originY: 'top'
});
canvas.on('mouse:over', function(e) {
var group = new fabric.Group([ rect, text ], {
left: e.target.left,
top: e.target.top
});
canvas.add(group);
canvas.renderAll();
});
canvas.on('mouse:out', function(e) {
//e.target.set('fill', 'green');
canvas.remove(group);
canvas.renderAll();
});
But when mouse:out fires i get:
Uncaught ReferenceError: group is not defined
at i.<anonymous> (can.js:38)
at i.r (fabric.min.js:1)
at i._fireOverOutEvents (fabric.min.js:3)
at i.findTarget (fabric.min.js:3)
at i.__onMouseMove (fabric.min.js:4)
at i._onMouseMove (fabric.min.js:4)
How can i make a group global with left and top of hovered element, or there is a better way to do that?
group is scoped as a private variable local to the mouse:over event. Try
removing var from:
var group = new fabric.Group([ rect, text ], {
to scope group globally:
group = new fabric.Group([ rect, text ], {
DEMO
var canvas = new fabric.Canvas('c');
var rect = new fabric.Rect({
originX: 'top',
originY: 'top',
width: 150,
height: 120,
fill: 'rgba(255,0,0,0.5)',
});
var text = new fabric.Text('hello world', {
fontSize: 30,
originX: 'top',
originY: 'top'
});
var group = new fabric.Group([ rect, text ], {
left: 0,
top: 0,
selectable : false,
visible: false,
});
canvas.add(group);
canvas.renderAll();
canvas.on('mouse:move', function(e) {
var p = canvas.getPointer(e.e);
group.set({
left: p.x,
top: p.y,
visible: true
});
canvas.renderAll();
});
canvas.on('mouse:out', function(e) {
group.set({
visible: false
})
canvas.renderAll();
});
canvas {
border:2px dotted blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.17/fabric.min.js"></script>
<canvas id='c' width=400 height=400></canvas>
You no need to create group on every mouse over, you just set visible: true/false, so according to this it will visible. Check DEMO.

Google chart throws error for invalid color due to values received using DataMap

Google chart throws error for invalid color due to values received using DataMap.
You can see colors: [colors], in options.
If i direct use color values like below then it works fine.
colors: ['#006400', '#3cb371', 'red', '#f5fffa'],
but if i get values through data map and it has same output then it doesn't work and throws error:
"'#006400' is not a valid color string".
Is there any kind of data formatting issue?
Sample JSON Data:
{"cols":[{"label":"status","type":"string"},{"label":"count","type":"string"}],"rows":[{"c":[{"v":"CLOSED"},{"v":3}]},{"c":[{"v":"VERIFIED"},{"v":35}]},{"c":[{"v":"RESOLVED"},{"v":15}]},{"c":[{"v":"IN_PROGRESS"},{"v":92}]},{"c":[{"v":"ASSIGNED"},{"v":63}]},{"c":[{"v":"NEW"},{"v":16}]},{"c":[{"v":""},{"v":0}]}]}
Custom color (problematic):
const DataMap = {
CLOSED: '#006400',
VERIFIED: '#006400',
RESOLVED: '#3cb371',
REOPENED: 'red',
IN_PROGRESS: '#f5fffa',
ASSIGNED: 'brown',
NEW: 'brown',
UNCONFIRMED: 'brown'
};
let myColors = [];
Object.keys(DataMap).forEach((key, index) => {
if (jsonData.search(key) !== -1) {
myColors.push("'" + DataMap[key] + "'");
}
});
options = {
title: chartTitle,
width: '410',
height: '320',
backgroundColor: '#f5fffa',
is3D: true,
colors: [myColors],
chartArea: {
left: "20%",
top: "20%",
height: "100%",
width: "100%"
}
};
chart.draw(data, options);
Direct color (works fine):
options = {
title: chartTitle,
width: '410',
height: '320',
backgroundColor: '#f5fffa',
is3D: true,
colors: ['#006400', '#3cb371', 'red', '#f5fffa'],
chartArea: {
left: "20%",
top: "20%",
height: "100%",
width: "100%"
}
};
chart.draw(data, options);
What can be the issue and how can i resolve it?
What I can say right now is:
myColors.push("'" + DataMap[key] + "'");
should be changed to
myColors.push(DataMap[key]);
because values for each key from DataMap are already strings, i.e. DataMap[key] is a string.
Secondly, instead of
colors: [myColors],
should be just
colors: myColors,
because myColors is already an array.

famo.us Firefox setting z-index doesn't work

I am trying to control the layering of surfaces using zIndex property. It works just fine in Chrome whereas it doesn't in Firefox. After examining the DOM, I observed that the z-index is marked as 0 no matter what we set.
I reproduced the problem in famo.us tutorial code #http://famo.us/university/famous-101/displaying/5/. Replace the tutorial code with the following code. Notice the difference between Chrome and Firefox with the same code.
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var mainContext = Engine.createContext();
var firstSurface = new Surface({
size: [200, 400],
content: 'top',
properties: {
color: 'white',
textAlign: 'center',
backgroundColor: '#FA5C4F',
zIndex: 10
}
});
var secondSurface = new Surface({
size: [300, 200],
content: 'bottom',
properties: {
color: 'white',
textAlign: 'center',
backgroundColor: 'green',
zIndex: 8
}
});
mainContext.add(firstSurface);
mainContext.add(secondSurface);
You should try to avoid using the zIndex property, because Famo.us does Z indexing for you with their 3D render Engine. To achieve what you wish, use a StateModifier and translate your surfaces in the Z direction.
This now works in FireFox as well. Hope it helps!
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var mainContext = Engine.createContext();
var firstSurface = new Surface({
size: [200, 400],
content: 'top',
properties: {
color: 'white',
textAlign: 'center',
backgroundColor: '#FA5C4F'
}
});
firstSurface.state = new StateModifier({
transform: Transform.translate(0,0,10)
});
var secondSurface = new Surface({
size: [300, 200],
content: 'bottom',
properties: {
color: 'white',
textAlign: 'center',
backgroundColor: 'green',
}
});
secondSurface.state = new StateModifier({
transform:Transform.translate(0,0,8)
});
mainContext.add(firstSurface.state).add(firstSurface);
mainContext.add(secondSurface.state).add(secondSurface);

How to assign attributes or functions to objects added after DOm ready with jquery

I am working in some personal project it is like the front-end of a chat. So i have my users and i have a JSON with the list of online and offline users. When the website firs load I also load plugins for custom scroll and make elements draggable with jquery ui. what i would like to know is if there is a way to make the new elements added to the body (chat windows) automatically be scrollable and have this custom scroll bar every time I add them. So far what I do es something like :
$(document).on("ready", functions);
function functions() {
$("#contacts-container").slimScroll({
height: '220',
size: '10px',
position: 'right',
color: '#535a61',
alwaysVisible: false,
distance: '0',
railVisible: true,
railColor: '#222',
railOpacity: 0.3,
wheelStep: 10,
disableFadeOut: false
});
$(".messages-container").slimScroll({
height: '200',
size: '10px',
position: 'right',
color: '#535a61',
alwaysVisible: false,
distance: '0',
railVisible: true,
railColor: '#222',
railOpacity: 0.3,
wheelStep: 10,
disableFadeOut: false,
start: "bottom"
});
$("#online .user-name").on("click", checkUser);
};
function checkUser(){
console.log("clicked");
var user = $(this).html();
$.getJSON("js/options.json", function(json){
var itemsLength = json.chat.OnlineContacts.length;
for ( var i = 0; i < itemsLength; i++) {
var jsonUserName = json.chat.OnlineContacts[i].name;
var jsonUserStatus = json.chat.OnlineContacts[i].status;
var jsonUserAvatar = json.chat.OnlineContacts[i].picture;
if(user == jsonUserName){
displayChatWindow(jsonUserName, jsonUserStatus, jsonUserAvatar);
}
};
});
}
function displayChatWindow(user, status, avatar){
console.log(avatar);
var template = _.template($("#windowTemplate").html(), {userName: user, userStatus: status, userAvatar: avatar});
$("body").prepend(template);
$(".messages-container").slimScroll({
height: '200',
size: '10px',
position: 'right',
color: '#535a61',
alwaysVisible: false,
distance: '0',
railVisible: true,
railColor: '#222',
railOpacity: 0.3,
wheelStep: 10,
disableFadeOut: false,
start: "bottom"
});
$(".friend-window").draggable({handler: ".header"});
}
On the DisplayChatWindow I append the template wich is s div representing the chat window, but i also have to re add the slimScroll function and the draggabla function, but i would like them to automatically have it once i append it, I am learning Java Script so I don't know if using an object i can achieve this or if there is another way, basically what i have done here it the most i know how to do so far, i will appreciate if you guys can help me :)
This should work I believe.
$(document).on("ready", function() {
functions();
$(document).bind('DOMNodeInserted', function() {
$(".messages-container").slimScroll({
height: '200',
size: '10px',
position: 'right',
color: '#535a61',
alwaysVisible: false,
distance: '0',
railVisible: true,
railColor: '#222',
railOpacity: 0.3,
wheelStep: 10,
disableFadeOut: false,
start: "bottom"
});
});
});

Categories

Resources