Nvd3 chart huge with oficial Css - html

I am having unexpected problems with a couple of Nvd3 charts. I coded them withouht using the nvd3 css file (nv.d3.min.css). Without it everything was ok but when I added it suddendly the second chart took a lot of space (1500x1500). The normal size was 450x450 but now it is
If i look in the console of chrome and uncheck the style atributes "width: 100%;" and "height: 100%;" it works (actually with only one). The other thing that changes de css atributes is the "user agent stylesheet".
I canĀ“t understand why because i thought that the size was explicitely coded while the configuration of the chart
HTML
<div id="charts">
<div id="piechart" ><svg></svg></div>
<div id="chart"><svg></svg></div>
</div>
NVD3
function setupGraph(data_graph) {
nv.addGraph(function() {
var pieChart = nv.models.pieChart();
pieChart.margin({top: 30, right: 60, bottom: 20, left: 60});
var datum = data_graph[0].values;
pieChart.tooltipContent(function(key, y, e, graph) {
var x = String(key);
var y = String(y);
tooltip_str = '<center><b>'+x+'</b></center>' + y;
return tooltip_str;
});
pieChart.showLabels(true);
pieChart.donut(false);
pieChart.showLegend(true);
pieChart
.x(function(d) { return d.label })
.y(function(d) { return d.value });
pieChart.width(450);
pieChart.height(450);
d3.select('#piechart svg')
.datum(datum)
.transition().duration(350)
.attr('width',450)
.attr('height',450)
.call(pieChart);
nv.utils.windowResize(chart.update);
return chart;
});
}
function setupGraph2(data_graph) {
nv.addGraph(function() {
var chart = nv.models.discreteBarChart()
.x(function(d) { return d.label }) //Specify the data accessors.
.y(function(d) { return d.value })
//.valueFormat(d3.format(',.2f'))
.staggerLabels(true) //Too many bars and not enough room? Try staggering labels.
.tooltips(false) //Don't show tooltips
.showValues(true) //...instead, show the bar value right on top of each bar.
.transitionDuration(350)
;
chart.width(450);
chart.height(450);
d3.select('#chart svg')
.datum(data_graph)
.attr('width',450)
.attr('height', 450)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
Can anybody see what is happening?

Just override the default width and height properties of the nvd3.css stylesheet, creating a rule in your stylesheet, and ensuring it is loaded after the nvd3 stylesheet.
The last rule (with the same specificity) wins:
svg {
width : auto;
height : auto;
}
or create a more specific rule to act on your svgs only, like:
#charts svg {
width : 450px;
height : 450px;
}

Related

Change IText color in Fabric.JS canvas (using React + typescript)

I have input with type=color outside Canvas. I have canvas with one ore more IText objects (as well as other objects). What I wanted to achieve is "on input change, change color of select text objects".
This is my input within React
<input type="color" defaultValue={defaultTextColor} ref={myRef} onChange={handleColorChange} />
I am able to change "text", but not color...
This is my Color Change event
const handleColorChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newColor = e.currentTarget.value;
canvas.getActiveObjects().forEach((element: any) => {
if(element.type == 'i-text') {
element.color = newColor; //this doesn't work
element.text = "new"; // this works
}
});
canvas.renderAll();
}
Firstly, the color of a text is defined in the property fill
Then you need to use the set and renderAll functions.
Here is an example
var canvas = new fabric.Canvas("canvas");
var myText = new fabric.Text("Hello", {
top: 100,
left: 100,
width: 60,
height: 70,
fill: "red",
});
setTimeout(() => {
myText.set("fill", "green");
canvas.renderAll();
}, 2000);
canvas.add(myText);

Why css styles behave that way?

I created small app using angular-cli based on 'Getting Started with Reactive Programming Using RxJS by Scott Allen' on Pluralsight. It creates Observable stream of events from mouse. Nothing fancy - stream of data works nice. The only problem is that styles are applied in a weird way for me. They update div only 2 times in an unknown way.
They are changed to 0px - once for x, once for y axis, when I move a mouse in an area of circle. One time and that's it. I changed manually these attributes in Developer Tools and it works like it should. But cannot laverage this behaviour automatically.
css html
#circle {
width: 50px;
height: 50px;
border-radius: 50%;
background-color: red;
position: absolute;
}
<div id="circle"></div>
Typescript
ngOnInit() {
let circle = document.getElementById('circle')
let mouse = fromEvent(document, 'mousemove')
.pipe(
map((e: MouseEvent) => {
return {
x: e.clientX,
y: e.clientY
}
}),
)
function onNext(value) {
circle.style.left = value.x
circle.style.top = value.y
console.log("xy", value.x, value.y)
}
mouse.subscribe(
value => onNext(value),
e => console.log(`error: ${e}`),
() => console.log('complete.')
)
}
add 'px' to value:
function onNext(value) {
console.log(circle.style.left)
circle.style.left = value.x + 'px'
circle.style.top = value.y + 'px'
console.log("xy", value.x, value.y)
}
and circle will change position by mouse. DEMO

Default background image with css and angularjs [duplicate]

I am adding background images to my div like this
ng-style="{'background-image' : 'url('+ myvariable.for.image +')'}">
where myvariable.for.image is a url like /examplesite/image/id
This works fine with one exception, if the image is not there it just doesnt do anything and my background looks too bla...If the image doesnt exist I want to be able to replace it with a default image.
But I cant seem to figure out how
Instead of ngStyle I'd use a custom directive for this. Such as the following. This checks to see if an attribute is provided, if so it attempts to load that image. If it loads an image then we set the background image to it, otherwise we use a default image.
myApp.directive('bgImage', function () {
return {
link: function(scope, element, attr) {
attr.$observe('bgImage', function() {
if (!attr.bgImage) {
// No attribute specified, so use default
element.css("background-image","url("+scope.defaultImage+")");
} else {
var image = new Image();
image.src = attr.bgImage;
image.onload = function() {
//Image loaded- set the background image to it
element.css("background-image","url("+attr.bgImage+")");
};
image.onerror = function() {
//Image failed to load- use default
element.css("background-image","url("+scope.defaultImage+")");
};
}
});
}
};
});
Used like this:
<div bg-image="{{person.src}}">
demo fiddle
<div err-bg-src='{{default_business_logo_wd}}' ng-style="{'background-image' : 'url('+ifNull(place.logo_wd,default_business_logo_wd)+')'}" id="perfilEstablecimiento-container10" class="place-header">
<div id="perfilEstablecimiento-container13" class="place-title-container">
<h4 id="perfilEstablecimiento-heading1" class="place-title">{{place.name}}</h4>
</div>
</div>
Using a $timeout inside that custom directive worked for me.
.directive
(
'errBgSrc',
function($timeout)
{
return {
link: function(scope, element, attrs)
{
$timeout
(
function()
{
if(window.getComputedStyle(document.getElementById(attrs.id)).backgroundImage=='none'||window.getComputedStyle(document.getElementById(attrs.id)).backgroundImage==null)
{
document.getElementById(attrs.id).style.backgroundImage='url('+attrs.errBgSrc+')';
}
else
{
var image = new Image();
var style=window.getComputedStyle(document.getElementById(attrs.id)).backgroundImage;
var url=style.slice(5,style.length-2);
image.src = url;
image.onerror = function()
{
document.getElementById(attrs.id).style.backgroundImage='url('+attrs.errBgSrc+')';
};
}
},
500
);
}
}
}
)

How to hide the overflow of photos in canvas?

I am trying making a photo frame pattern on canvas. In which I want to put two, three or maybe more photos under an overlay frame. Where few parts of the overlay frame are transparent.
If I upload photo1 into first section of frame its visible into second section also and uploading photo2 into section two is also visible into first section. Depending on which photo is uploaded first or edited at last is overlapping the other photo.
I want to know how to hide the overflow of photo so it should not be visible into other sections. How can I achieve this?
I have done this so far:
canvas.on({
'object:moving': onChange,
'object:scaling': onChange,
'object:rotating': onChange,
});
function onChange(options) {
options.target.setCoords();
canvas.forEachObject(function (obj) {
if (obj === options.target)
return;
if (obj.id != 'cover1' && obj.id != 'cover2')
return;
if (options.target.intersectsWithObject(obj)) {
// Hide this portion
canvas.renderAll();
}
});
}
Kindly provide me the best solution
You need to apply a clipTo() method onto the image.
var canvas;
$(function(){
canvas = window._canvas = new fabric.Canvas('canvas');
var radius = 200;
fabric.Image.fromURL('http://fabricjs.com/assets/pug_small.jpg', function(img) {
img.scale(0.5).set({
left: 250,
top: 250,
angle: -15,
clipTo: function (ctx) {
ctx.arc(0, 0, radius, 0, Math.PI * 2, true);
}
});
canvas.add(img).setActiveObject(img);
});
});
This fiddle show the technique
Fiddle

mxGraph cell resize and graph layout

I'm having problems with resizing cells and built-in mxGraph layouts.
If I put a cell on canvas, and I try to resize it, even for a pixel, it grows huge, something like 50000px x 30000px, so it streches my whole canvas, and of course it is unusable.
If I load a graph from an xml file from the database, I can resize cells without any problems.
Similar thing happens with the built in layouts. I'd like to use compact tree layout (the reason I like it beacuse it aligns my whole horizontal).
When I draw a graph and try to use that layout, my graph goes wild, also streching to 50000px x 30000 px (example dimensions, but the scroll is so tiny I can barely aim it with the mouse).
If I load a graph from xml from a database, compact tree layout works perfect. But as soon as I add another cell in it, and try to use compact tree layout again, it goes wild, again.
I use absolute positioning for div which holds the canvas, as same as on the example here (http://jgraph.github.io/mxgraph/javascript/examples/editors/workfloweditor.html)
This is my css and html :
<head>
<style type="text/css">
#graphContainer {
background: url('../../resources/jgraph/src/images/grid.gif');
left: 20px;
right: 20px;
top: 65px;
bottom: 20px;
position: absolute;
border: 1px solid #F2F2F2;
white-space: nowrap;
font-family: Arial;
font-size: 8pt;
display: block;
}
</style>
</head>
<body>
<div id="graphContainer"></div>
<script>
$(document).ready(function(){
mc.init(document.getElementById('graphContainer'));
});
</script>
</body>
</html>
And this is my javascript for graph initialization (along with the couple of events, beacuse I'm not sure if they are the problem):
mxConnectionHandler.prototype.connectImage = new mxImage('../../resources/jgraph/src/images/connector.gif', 14, 14);
if (!mxClient.isBrowserSupported()) {
mxUtils.error('Browser is not supported!', 200, false);
} else {
var root = new mxCell();
root.insert(new mxCell());
var model = new mxGraphModel(root);
if (mxClient.IS_QUIRKS)
{
document.body.style.overflow = 'hidden';
new mxDivResizer(graphContainer);
}
var editor = new mxEditor();
editor.setGraphContainer(graphContainer);
editor.readGraphModel(model);
var graph = editor.graph;
graph.setConnectable(true);
new mxRubberband(graph);
/* CODE FOR ADDING THE TOOLBAR, excluded from example */
//code for writing out the node name
graph.convertValueToString = function(cell)
{
if (mxUtils.isNode(cell.value))
{
var outValue = cell.value.getAttribute('nodeName');
if (outValue != null && outValue.length > 0)
{
return outValue;
}
return '';
}
return '';
};
//defining on select event
graph.getSelectionModel().addListener(mxEvent.CHANGE, function(sender, evt)
{
events.cellSelectionChanged(graph, graph.getSelectionCell());
});
//triggering the on select event
events.cellSelectionChanged(graph);
//cells added event
graph.addListener(mxEvent.CELLS_ADDED, function(sender, evt) {
var vertex = evt.getProperties().cells[0];
if(vertex.isVertex()){
var decoder = new mxCodec();
var nodeModel = decoder.decode(vertex.value);
if(nodeModel.type=='node' || nodeModel.type=='branch'){
utils.changeCellAttribute(vertex, 'nodeName', 'Node_' + vertex.id);
}else if(nodeModel.type=='start'){
utils.changeCellAttribute(vertex, 'nodeName', 'START');
}else if(nodeModel.type=='end'){
utils.changeCellAttribute(vertex, 'nodeName', 'END');
}else if(nodeModel.type=='form'){
utils.changeCellAttribute(vertex, 'nodeName', 'Form');
}
}
});
//on connect event
graph.connectionHandler.addListener(mxEvent.CONNECT, function(sender, evt){
var model = graph.getModel();
var edge = evt.getProperty('cell');
var source = model.getTerminal(edge, true);
var target = model.getTerminal(edge, false);
});
}
Any thoughts what the problem might be?
Solution:
Complete graph and cell configuration is loaded from the database (in this example), including the width and height for the cells.
The problem was adding toolbar items for certain cell types, more precise, dropped cell default width and height. As I said we are loading the configuration from the database, it is completely string-ified, so were the width and height.
They both had to be cast to JavaScript Number object for resize and layout to behave properly.