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 });
Related
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.
i want to show/hide my raphael svg graph with a button click event
please someone who know how to do this. please help me
i try to do by this way but it's not working.
var p = Raphael(900,70,200,200);
p.circle(20,20,20);
$n("#shide").click(function(){
p.hide();
});
please someone who know how to do this. please help me.
Thanks in advance.
You'd better use the return value of drawing functions.
var element1 = p.circle(20,20,20);
var element2 = p.circle(99,99,20);
$n("#shide").click(function(){
element1.hide();
// element2.hide();
});
Also I have some advanced skills about this kind of problem. These skills will be very usefull when you draw your circles or other things with the ajax response data.
function drawCircle() {
var elementObj = {};
$.ajax({url: '', dataType: 'json', method: 'post', data: yourData, success: function (data) {
elementObj['circle1'] = p.circle(20,20,20);
elementObj['circle2'] = p.circle(99,99,20);
});
return elementObj;
}
Then you call this function like this:
var ele = drawCircle();
var hoverInCb = function () {
ele['circle1'] && ele['circle1'].show();
ele['circle2'] && ele['circle2'].show();
};
var hoverOutCb = function () {
ele['circle1'] && ele['circle1'].hide();
ele['circle2'] && ele['circle2'].hide();
};
These code will work because that the returned elementObj is a 'link' of the object. After the data fetched by ajax request, the elementObj will be filled with data, and the ele variable outside there will also get the new data.
Like this:
var paper = Raphael(10, 50, 320, 200);
paper.circle(10, 10, 10, 10)
.attr({fill: "#000"})
.click(function () {
this.hide();
});
I have a rectangle which glows on mousedown event & glow disappears at mouseup event. The issue is when I drag the rectangle, the glow persists on the canvas!
Here's my code for clarity:
window.onload = function(){
var paper = new Raphael("holder",500,500);
var myRect = paper.rect(200,200,200,100,10);
myRect.attr({
fill: "#999",
stroke: "#555",
'stroke-width': 5
});
myRect.mousedown(function(){
this.g = myRect.glow();
}
);
myRect.mouseup(function(){
this.g.remove();
});
var start = function(){
this.ox = this.attr('x');
this.oy = this.attr('y');
},
move = function(dx,dy){
var att = {x:this.ox+dx,y:this.ox+dy};
this.attr(att);
},
up = function(){
//
};
myRect.drag(move,start,up);
}
You can remove the glow of the object on start and apply it again on up. In this way the shadow wont be visible while you're draggin the object but will be there when you'll drop the object.
Here is the fiddle with your example.
First of all, you shouldn't use this inside an anonymous function because the scope of this is just available in there.
Second, you don't need myRect.mousedown and myRect.mouseup because you handle those we the callbacks inside your myRect.drag (start and up)
So i made you a fiddle where you can see it working.
P.S. There seems to be another bug with the positioning: when you drag a few times the rectangle gets shifted away from the cursor.
I would like to know if it is possible to retrieve the new path after animation, I tried :
var p =
canevas.path("M0,0,100,20").animate({transform:"t100,100"},500,"none",function
() {alert(this.attr("path"));})
but alert alerts me the original path without taking into account the transformation .
Is there a way to do this ?
Thank you
V.Bonnet
You can use the Raphael.transformPath method to get the path with the transformation 'baked in'. To use your example:
var paper = Raphael(10, 10, 300, 300);
var line = paper.path("M0,0,100,20");
line.animate({ transform: "t100,100" }, 500, "none", function() {
var transform = this.attr('transform');
var transformedPath = Raphael.transformPath(this.attr('path'), transform);
console.log("original path:", this.attr('path').toString());
console.log("transform:", transform.toString());
console.log("new path:", transformedPath.toString());
})
This will yield:
original path: M0,0L100,20
transform: t100,100
new path: M100,100C100,100,200,120,200,120
See it in action here: http://jsfiddle.net/seeligd/HCUey/3/
When translating in Raphael 2.x it doesn't modify the path, it adds a transformation such as...
<path fill="none" stroke="#000000" d="M0,0L100,20" transform="matrix(1,0,0,1,100,100)"></path>
I recall that Raphael 1.x used to modify the path, but this is no longer true. To find out how the element was transformed you can try...
var p = canevas.path("M0,0,100,20").animate({transform:"t100,100"},500,"none",function () {alert(this.attr("transform"));})
and it will return t100t100 which you have to parse manually.