How do you serialize and deserialize a custom Konva Shape?
Konva allows you to create a custom shape with the sceneFunc, but when you store it to JSON and load it back, how do you know what custom shape it is?
To define a custom shape you need to define sceneFunc Demo:
function mySceneFunc(context, shape) {
context.beginPath();
context.rect(0, 0, shape.getAttr('width'), shape.getAttr('height'));
context.fillStrokeShape(shape);
}
var rect = new Konva.Shape({
fill: '#00D2FF',
width: 100,
height: 50,
name: 'my-custom-rect',
sceneFunc: mySceneFunc
});
It is not recommended to serialize functions into JSON. So by default node.toJSON() will not have sceneFunc property.
To restore your custom shape you just need to find such shapes in your stage after deserialization and then apply sceneFunc manually. You can set your own name to such shapes to easily find them.
var json =
'{"attrs":{"width":758,"height":300},"className":"Stage","children":[{"attrs":{},"className":"Layer","children":[{"attrs":{"fill":"#00D2FF","width": 100, "height": 100, "name": "my-custom-rect" },"className":"Shape"}]}]}';
// create node using json string
var stage = Konva.Node.create(json, 'container');
function mySceneFunc(context, shape) {
context.beginPath();
context.rect(0, 0, shape.getAttr('width'), shape.getAttr('height'));
context.fillStrokeShape(shape);
}
stage.find('.my-custom-rect').sceneFunc(mySceneFunc);
stage.draw()
Demo: https://jsbin.com/sadehigina/1/edit?html,js,output
Related
I want to access the data in a list that is in another class (class RubricItem). The color must be the one with the corresponding id.
Then I would like to insert the data from the list that I called from the RubricItem class into the list that are in the Colors class. In the Colors class is the parameter id :. And depending on which ID I typed in, my "rubricColor:" should know what its value should be.
Example:
I write down the id value of the list from the Colors class 'BlueAccent', then he also has to know which color has to be written in rubricColor:. He sees 'BlueAccent' at the id: from the Colors class and compares this with the id: in the list from the RubricItem class and sees the color value in the same list from the RubricItem class and my rubricColor: value in the list the Colors class, takes the value of color from the list of the RubricItem class.
I hope you understand what I mean.
It was very difficult for me to explain.
RubricItem class:
class _RubricItemState extends State<RubricItem> {
final List<Rubric> rubrics = [
Rubric(
id: 'BlueAccent',
title: "BLUEACCENT",
color: Colors.blueAccent,
icon: 'assets/icons/blueAC.png',
),
Rubric(
id: "Pink",
title: "PINK",
color: Colors.pinkAccent,
icon: 'assets/icons/PINK.png',
),
Rubric(
id: 'GreenAccent',
title: "GREENACCENT",
color: Colors.greenAccent,
icon: 'assets/icons/GreenAccent.png',
),
];
...
List of Color classes:
final List<Colorr> colors = [
Colorr(
id: 'BlueAccent', // with this id he should be find the id in the List of the RubricItem() class
title: 'Blabla',
rubric: '',
rubricColor: , //(RubricItemColor)
),
];
Use maps instead of lists.
map<String, Rubric>
map<String, Colorr>
and the Strings are the ids. And then just use the ids
Edit1: example
I don't know if this is the best way to approach your problem but it works.
I used the key of the map as the id and removed the id from both Rubric class and Colorr class.
import 'package:flutter/material.dart';
void main() {
final Map<String,Rubric> rubrics = {
'BlueAccent': Rubric(title:'BLUEACCENT',color: Colors.blueAccent, icon: 'assets/icons/blueAC.png'),
};
final Map<String, Colorr> colors = {
'BlueAccent': Colorr(title: 'title', rubric:rubrics['BlueAccent'],rubricColor: rubrics['BlueAccent'].color),
};
}
class Rubric{
Rubric({this.title,this.icon,this.color});
final String title;
final Color color;
final String icon;
}
class Colorr{
Colorr({this.title,this.rubric,this.rubricColor});
final String title;
final Rubric rubric;
final Color rubricColor;
}
I am trying to create a line chart plugin that will draw reference letters under some points. To do so, the plugin uses a custom afterDatasetsDraw function to perform the drawing. However, I am unable to find a way to pass in the reference letters for the desired points. Below is an example of what I'm trying to achieve with the red circled letters.
Does anyone have an idea on how to pass in the reference letters for the corresponding points?
Thanks.
I would just define some configuration properties for your new plugin and use one of those properties to define where the point reference should be located and what the reference value should be.
Here is an example of what I mean. This would be in the chart's options property.
pointReferenceLetters: {
display: true,
fontColor: 'green',
references: [
{datasetIndex: 0, dataIndex: 1, reference: 'A'},
{datasetIndex: 1, dataIndex: 2, reference: 'B'},
]
}
The plugin would then use this data to draw the point references. Here is an example showing how a plugin would use this data. Note, I just did a quick implementation to show the concept, this plugin does not draw the reference circle like yours would.
Chart.plugins.register({
afterDraw: function(chartInstance) {
if (chartInstance.config.options.pointReferenceLetters || chartInstance.config.options.pointReferenceLetters.display) {
var references = chartInstance.config.options.pointReferenceLetters.references || [];
var helpers = Chart.helpers;
var ctx = chartInstance.chart.ctx;
var fontColor = helpers.getValueOrDefault(chartInstance.config.options.pointReferenceLetters.fontColor, chartInstance.config.options.defaultFontColor);
// render the value of the chart above the bar
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize + 5, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.fillStyle = fontColor;
chartInstance.data.datasets.forEach(function (dataset, dsindex) {
for (var i = 0; i < dataset.data.length; i++) {
// note, many browsers don't support the array.find() function.
// if you use this then be sure to provide a pollyfill
var refPoint = references.find(function(e) {
return e.datasetIndex == dsindex && e.dataIndex === i
});
if (refPoint) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
ctx.fillText(refPoint.reference, model.x, model.y + 30);
}
}
});
}
}
});
As you an see, the plugin uses the data provided in the pointReferenceLetters.references property to determine when a point reference should be drawn and then uses the values provided as the reference text.
Here is a codepen example that demonstrates all of this.
i had already done adding a click handler to each Segment of my doughnut chart with adding the following Code :
$("#myChart").click(
function(evt){
var activePoints = myNewChart.getSegmentsAtEvent(evt);
var chartelementid = activePoints[0].label;
alert(chartelementid);
//$('.details div').css("display", "none");
//$('#' + chartelementid).show();
}
);
This works fine, when finished it should display an additional Div with Details for this segment.
Unfortunality my labels are more then just Single Words, so i'm struggeling to create div ID's with the same name...
My Idea is to add to every Segment an additional Data like value,label, etc. so it could be an ID. but if i just add the ID information to the Segment it will not exist as variable.
Add DataType:
var dataImprove = [
{
value: 30,
color:"#001155",
highlight: "#1c2f7c",
label: "KnowHow Erhalt / Transfer & Aufbau",
id:"test"
}
]
where can i add in chart.js an additional dataType like shown above my ID to be accessible in the DOM?
kind regards Marco
As an alternative pass a JSON string as your label, then intercept to render. For example:
var canvas = document.getElementById(id);
var d = canvas.getContext("2d");
var chart = new Chart(d).Pie(json, {
segmentStrokeWidth: 1,
tooltipTemplate: "<%=label%>", //default the label
customTooltips: function (tooltip) {
// Hide if no tooltip
if (!tooltip) {
return;
}
var tooltipObj = JSON.parse(tooltip.text);
// etc
already found : between line 999 and 1023 in chart.js before drawing - i've added the line
id: ChartElements[0].id,
so the Data with the name ID is in the DOM avaiable.
var circle = paper.getById(data.Id);
console.log("circle : " + circle);
circle.attr({ opacity: data.Opacity / 100 });
console output:
circle : Raphaël’s object
and
Uncaught TypeError: Cannot call method 'attr' of null
I think, first I convert object to circle? How can I change element attribute?
Thanks...
Its not really clear what your data object is, to know if thats correct, or if the id has been set. Here is an example.. with a fiddle here http://jsfiddle.net/Uvcy9/2/
var paper = Raphael('container',200,200);
var newCircle = paper.circle(100,20,20);
newCircle.id='circle1';
paper.add( newCircle );
/// some code here, later we want to reference it...
var circle = paper.getById('circle1');
circle.attr({ fill: 'red', opacity: circle.attr('opacity') / 10 });
I have a function:
function images_styles(Isel){
if (Isel==1){
var marker_pic="/sites/all/themes/shakhty/images/map/icons/1.png";
}
else{
var marker_pic="http://www.openlayers.org/dev/img/marker.png";
}
var styleImage = new OpenLayers.Style({
graphicWidth: 43,
graphicHeight: 65,
graphicYOffset: -28,
label: "${label}",
externalGraphic: marker_pic,
fontSize: "1em",
strokeOpacity:5
});
var vectorImage = new OpenLayers.Layer.Vector("Images", {
styleMap: new OpenLayers.StyleMap({
"default": styleImage
})
});
map.addLayer(vectorImage);
}
I want to change images (marker_pic) when user chooses variant in form. But when the variant has choosen for the first time, the image doesn't change, until i reload page.
What should i do?
How to refresh images every time user choose another variant?
To update your vector layer with a new external graphic, try the following:
vectorImage.refresh({force:true});
Alternatively, the following should work as well:
vectorImage.redraw();