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
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);
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.
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.
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);
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"
});
});
});