I'm having difficulty centering my D3 map on the webpage. The map is in a map class and within a div, but CSS won't appear to center it.
Any margins I apply to the class ".map", which the SVG is in, doesn't appear to work either. I'm not sure why I'm unable to apply any CSS to the map, but maybe I'm supposed to do something in the actual D3 code? Unsure. Thanks!
Here's my code:
<!DOCTYPE html>
<html>
<head>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.js'></script>
<meta charset='utf-8'>
<meta name="viewport" content='width=device-width, initial-scale=1.0'>
<title></title>
<style>
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 10px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 10px;
}
.active {
fill: rgba(149, 165, 166, 0.8);
}
body {
background: rgba(32, 32, 32, 1);
color: rgba(255, 255, 255, 0.8);
}
h1 {
font-family: Impact, Charcoal, sans-serif;
text-align: center;
}
h2 {
font-family: Impact, Charcoal, sans-serif;
text-align: center;
}
p {
font-family: "Arial Black", Gadget, sans-serif;
text-align: center;
}
#box {
border: 10px solid black;
margin: auto;
padding: 10px;
width: 75%;
border-radius: 10px;
}
.map {
margin-left: auto;
margin-right: auto;
}
</style>
<script>
function draw(geo_data) {
var margin = 0,
width = 2000 - margin,
height = 700 - margin;
var centered;
var svg = d3.select('#map')
.append('svg')
.attr('width', width + margin)
.attr('height', height + margin)
.append('g')
.attr('class', 'map');
var formatComma = d3.format(",")
var projection = d3.geoAlbersUsa();
var path = d3.geoPath().projection(projection);
var map = svg.selectAll('path')
.data(geo_data.features)
.enter()
.append('path')
.attr('d', path)
.attr('fill', 'rgba(105, 105, 105, 1)')
.attr('stroke', 'rgba(0, 0, 0, 1)')
.attr('stroke-width', 0.5)
.on('mouseover', function(d) {
d3.select(this).attr('fill', 'rgba(108, 122, 137, 0.5)')
})
.on('mouseout', function() {
if (d3.select(this).classed('clicked')) {
console.log('is clicked')
d3.select(this).attr('fill', 'rgba(105, 105, 105, 1)')
} else {
console.log('is not clicked')
d3.select(this).attr('fill', 'rgba(105, 105, 105, 1)')
}
})
// Calls click-to-zoom function defined below.
.on('click', clicked);
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<p><font size='4rem'>" + d.city + ", " + d.state + "</p></font>" + "<p><font size='3rem'><strong>Guns Manufactured: </strong>" + formatComma(d.guns) + "</p>" +
"<p><strong>Top Manufacturer:</strong> " + d.manufacturer +
"</p></font>";
})
svg.call(tip);
// Click-to-zoom function adapted from Mike Bostock's code: https://bl.ocks.org/mbostock/2206590
function clicked(d) {
d3.select(this).attr('fill', 'rgba(108, 122, 137, 0.5)');
if (d3.select(this).classed('clicked')) {
d3.select(this).attr('clicked', false);
} else {
d3.select(this).attr('clicked', true);
}
var x, y, k;
if (d && centered !== d) {
var centroid = path.centroid(d);
x = centroid[0];
y = centroid[1];
k = 4;
centered = d;
} else {
x = width / 2;
y = height / 2;
k = 1;
centered = null;
}
map.selectAll('path')
.classed('active', centered && function(d) {
return d === centered;
});
map.transition()
.duration(1000)
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')scale(' + k + ')translate(' + -x + ',' + -y + ')')
.style('stroke-width', 1 / k + 'px');
// Transitions circles upon zoom.
svg.selectAll('circle')
.transition()
.duration(1000)
.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')scale(' + k + ')translate(' + -x + ',' + -y + ')')
.style('stroke-width', 1 / k + 'px');
}
d3.csv('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/top100cities.csv', function(error, data) {
// Converts strings in csv to integers so they can be used.
data.forEach(function(d) {
return d.guns = +d.guns;
})
// This returns the max number of guns.
var guns = data.map(function(d) {
return d.guns;
});
var guns_extent = d3.extent(data, function(d) {
return d.guns;
});
var radius = d3.scaleSqrt()
.domain(guns_extent)
.range([2, 40]);
svg.append('g')
.attr('class', 'bubble')
.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('cx', function(d) {
return projection([d.lon, d.lat])[0];
})
.attr('cy', function(d) {
return projection([d.lon, d.lat])[1];
})
.attr('r', function(d) {
return radius(d.guns);
})
.attr('fill', 'rgba(248, 148, 6, 0.5)')
.attr('stroke', 'black')
.on('mouseover', function(d) {
tip.show(d);
return d3.select(this).attr('fill', 'rgba(248, 148, 6, 0.9)');
})
.on('mouseout', function(d) {
tip.hide(d);
return d3.select(this).attr('fill', 'rgba(248, 148, 6, 0.5)');
})
});
};
</script>
</head>
<body>
<div id='box'>
</div>
<div id='map'>
<h2>Hover your mouse to see data on the cities and click a state to zoom in.</h2>
</div>
<div id='box'>
</div>
<script>
d3.json('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/us_states.json', draw);
</script>
</body>
Enclose the map in another div, which has the same width as the box above it (75%). You may want to move the div style to a CSS class, if it works the way you want.
<div style="display:block; margin-left:auto; margin-right:auto; width:75%">
<div id="map">
...
</div>
</div>
UPDATE
I just found the real problem. Your css definition for map is for a class, not for an id. And... if you want to use auto margins, you need to define a width.
Change your css to match the following:
#map {
width: 75%;
margin-left: auto;
margin-right: auto;
}
Related
I want my tooltip to be aligned next to the hovered element. How can I find the position of hovered element such that it works in devices also. I am passing the hovered element event on mouseenter.
I tried setting the ClientX, ClientY or screenX, ScreenY position to top and left but it's not working properly.
Example
As you dont provided any code source I created a sample to show what you can do:
var ul = document.querySelector('ul');
var li = ul.querySelectorAll('li');
var tooltip = document.querySelector('.tooltip');
var removeTooltip;
function onMouseOver(e) {
return function() {
clearTimeout(removeTooltip);
tooltip.innerHTML = e.innerHTML;
var w = window;
var tooltipTopPosition = e.offsetTop + (e.clientHeight / 2) - (tooltip.clientHeight / 2);
var leftPosition = e.offsetLeft + e.offsetWidth + 5;
var toolTipWidth = w.innerWidth - leftPosition - 5;
tooltip.style.top = tooltipTopPosition + 'px';
tooltip.style.left = leftPosition + 'px';
tooltip.style.width = toolTipWidth + 'px';
}
}
function onMouseLeave(e) {
return function() {
clearTimeout(removeTooltip);
removeTooltip = setTimeout(function() {
tooltip.innerHTML = '';
}, 100);
};
}
li.forEach(function(item) {
item.onmouseover = onMouseOver(item);
item.onmouseleave = onMouseLeave(item);
});
.tooltip {
background: rgba(0,0,0,0.9);
color: #ffffff;
position: absolute;
z-index: 1000;
word-break: break-all;
white-space: normal;
}
ul {
width: 200px;
margin: 50px auto 0;
padding: 0;
}
ul li {
list-style-type: none;
background: #ccc;
padding: 5px;
border: 1px dotted;
}
<ul>
<li>Lorem.</li>
<li>Necessitatibus.</li>
<li>Dolorum.</li>
<li>Est.</li>
</ul>
<div class="tooltip"></div>
I am trying to create a collapsible tree graph in d3. Although there are many examples around the web, I am not expert in JS or d3 coming from java background, and couldn't find any that perfectly suited my needs and hence made this from different templates that I found across many blogs and gists.
The problem is the lower part of my graph getting clipped. If I increase the svg size, that just elongates the graph and it still gets clipped. I am posting the link to plunkr where I have put the code. Please scroll to the right in plunkr to see the graph.
Below is the javascript to render tree
var CollapsibleTree = function(elt) {
var m = [20, 120, 20, 120],
w = 1280 - m[1] - m[3],
h = 780 - m[0] - m[2],
i = 0,
root;
var tree = d3.layout.tree()
.size([w, h]);
var parentdiagonal = d3.svg.diagonal()
.projection(function(d) { return [d.x, -d.y]; });
var childdiagonal = d3.svg.diagonal()
.projection(function(d) { return [d.x, d.y]; });
var vis = d3.select(elt).append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate("+w/6+","+h/2+")"); // bidirectional-tree
var that = {
init: function(url) {
var that = this;
var json = {
"name":"A",
"elementType":"ACTION",
"elementSubType":"ACTION-A",
"isparent":false,
"parents":[
{
"name":"B",
"elementType":"RESOURCE",
"elementSubType":"RESOURCE-A",
"isparent":true
}
],
"children":[
{
"name":"C",
"elementType":"RESOURCE",
"elementSubType":"RESOURCE-C",
"isparent":false,
"children":[
{
"name":"D",
"elementType":"ACTION",
"elementSubType":"ACTION-A",
"isparent":false,
"children":[
{
"name":"E",
"elementType":"RESOURCE",
"elementSubType":"RESOURCE-A",
"isparent":false,
"children":[
{
"name":"F",
"elementType":"ACTION",
"elementSubType":"ACTION-C",
"isparent":false,
"children":[
{
"name":"G",
"elementType":"RESOURCE",
"elementSubType":"RESOURCE-C",
"isparent":false
}
]
}
]
}
]
}
]
}
]
};
root = json;
root.x = w / 2;
root.y = h / 2;
that.updateBoth(root);
},
updateBoth: function(source) {
var duration = d3.event && d3.event.altKey ? 5000 : 300;
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse();
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 0.5*h/4; });
// Update the nodes…
var node = vis.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("svg:g")
.attr("class", "node")
.attr("transform", function(d) {
if( that.isParent(d) ) {
return "translate(" + source.x + "," + -source.y + ")";
} else {
return "translate(" + source.x + "," + source.y + ")";
}
})
.on("click", function(d) { that.toggle(d); that.updateBoth(d); });
// Add images to node
nodeEnter.append("svg:image")
.attr("xlink:href", "img/file.png")
.attr("width", 35)
.attr("height", 35)
.attr("x",function(d) { return -20; }) // position the images
.attr("y",function(d) { return -20; });
nodeEnter.append("text")
// .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
.attr("x", function(d) {
return -10;
})
.attr("y", 20)
.attr("dy", ".35em")
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
.attr("text-anchor", function(d) {
return "middle";
})
.text(function(d) {
if (d.name.length > 10){
return d.name.substring(0,10)+d.name.substring(10,d.name.length);
}
else {
return d.name;
}
})
.style("fill", "black")
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.ease("linear")
.attr("transform", function(d) {
if( that.isParent(d) ) {
return "translate(" + d.x + "," + -d.y + ")";
} else {
return "translate(" + d.x + "," + d.y + ")";
}
});
nodeUpdate.select("text")
.style("fill-opacity", 1)
.attr("class", function(d){
if (d.status==="incomplete" || d.status === "failed"){
return "blink";
} else {
return "non-blink"
}
});
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
// .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
.attr("transform", function(d) { // custom code to fix error in node exit
if (that.isParent(d)){
return "translate(" + source.x + "," + -source.y + ")"; // controls exit of parents
}
else{
return "translate(" + source.x + "," + source.y + ")"; // controls exit of children
}
})
.remove();
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = vis.selectAll("path.link")
.data(tree.links_parents(nodes).concat(tree.links(nodes)), function(d) { return d.target.id; });
// Enter any new links at the parent's previous position.
link.enter().insert("svg:path", "g")
.attr("class", "link")
.style("stroke", function(d) {
return "black";
})
.attr("d", function(d) {
var o = {x: source.x, y: source.y};
if( that.isParent(d.target) ) {
return parentdiagonal({source: o, target: o});
} else {
return childdiagonal({source: o, target: o});
}
})
.transition()
.duration(duration)
.attr("d", function(d) {
if( that.isParent(d.target) ) {
return parentdiagonal(d);
} else {
// return parentdiagonal(d);
return childdiagonal(d);
}
})
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", function(d) {
if( that.isParent(d.target) ) {
return parentdiagonal(d);
} else {
return childdiagonal(d);
}
})
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {x: source.x, y: source.y};
// return parentdiagonal({source: o, target: o});
if( that.isParent(d.target) ) {
return parentdiagonal({source: o, target: o});
} else {
return childdiagonal({source: o, target: o});
}
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x = d.x;
d.y = d.y;
});
},
isParent: function(node) {
if( node.parent && node.parent != root ) {
return this.isParent(node.parent);
} else
if( node.isparent ) {
return true;
} else {
return false;
}
},
// Toggle children or parents (one level).
toggle: function(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
if (d.parents) {
d._parents = d.parents;
d.parents = null;
} else {
d.parents = d._parents;
d._parents = null;
}
},
// Toggle successors or aancestors (multiple level)
toggleAll: function(d) {
if (d.children) {
d.children.forEach(that.toggleAll);
that.toggle(d);
}
if (d.parents) {
d.parents.forEach(that.toggleAll);
that.toggle(d);
}
}
}
return that;
}
and here are the css
body {
overflow: hidden;
margin: 0;
font-size: 14px;
font-family: "Helvetica Neue", Helvetica;
}
#chart, #header, #footer {
position: absolute;
top: 0;
}
#header, #footer {
z-index: 1;
display: block;
font-size: 36px;
font-weight: 300;
text-shadow: 0 1px 0 #fff;
}
#header.inverted, #footer.inverted {
color: #fff;
text-shadow: 0 1px 4px #000;
}
#header {
top: 80px;
left: 140px;
width: 1000px;
}
#footer {
top: 680px;
right: 140px;
text-align: right;
}
rect {
fill: none;
pointer-events: all;
}
pre {
font-size: 18px;
}
line {
stroke: #000;
stroke-width: 1.5px;
}
.string, .regexp {
color: #f39;
}
.keyword {
color: #00c;
}
.comment {
color: #777;
font-style: oblique;
}
.number {
color: #369;
}
.class, .special {
color: #1181B8;
}
a:link, a:visited {
color: #000;
text-decoration: none;
}
a:hover {
color: #666;
}
.hint {
position: absolute;
right: 0;
width: 1280px;
font-size: 12px;
color: #999;
}
.node circle {
cursor: pointer;
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font-size: 11px;
}
path.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
/*svg {
border: 1px;
border-style: solid;
border-color: black;
}*/
#foo {
border: 5px;
border-style: dashed;
border-color: black;
background-color: pink;
}
#categoryHierarchy{
margin: 5px;
height: 700px;
width: auto;
border: 2px;
border-style: solid;
border-color: #000;
overflow: scroll;
/*padding: 10px;*/
}
and html files
<body>
<div id="categoryHierarchy"></div>
<script type="text/javascript">
$(document).ready(function(event) {
var tree = CollapsibleTree("#categoryHierarchy");
tree.init('sample.json');
});
</script>
</body>
You could try reducing the distance between each of the 'nodes'.
E.g. line 98 try playing around with h - 'x', I've tried using 300.
nodes.forEach(function(d) { d.y = d.depth * 0.5*(h-300)/4; });
if(!CSS.supports('cursor', 'url(cursor.png), pointer')) {
var myCursor = document.createElement('img');
myCursor.src = 'cursor.png';
myCursor.style.position = 'absolute';
document.body.appendChild(myCursor);
document.addEventListener('mousemove', function(e) {
myCursor.style.left = e.pageX+'px';
myCursor.style.top = e.pageY+'px';
}, false);
}
body{
padding:0;
margin:0;
background-color: #19321D;
color: #53CC66;
line-height: 1.5;
font-family: FreeMono, monospace;
cursor: url(cursor.png), pointer;
}
a{
text-decoration: none;
color: #53CC66;
}
ul{
text-decoration: none;
list-style-type: none;
}
#header{
text-align: center;
border-bottom: 3px solid #53CC66;
margin-bottom: 100px;
width: 90%;
margin-left: auto;
margin-right: auto;
margin-top: 25px;
line-height: 1;
}
h1, h2, h3{
color: #53CC66;
font-family: FreeMono, monospace;
font-size: 15px;
}
a{
cursor: url(cursor.png), pointer;
}
a:hover {
cursor: url(cursor.png), pointer;
color: #19321D;
}
li:hover{
background-color:#53CC66;
color: #19321D;
}
li:hover a{
color: #19321D;
}
<html>
<head>
<title>Getrate|Command promph </title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="styles15.css" type="text/css" />
</head>
<body>
<div id="wrapper">
<div id="header">
<h1>DAVID SECRET INDUSTRIES UNVERIFIED SYSTEM</h1>
<h2>COPYRIGHT 2015 - 2050 ALL RIGHT RESERVED</h2>
<h3>- SERVER #1 -</h3>
</div>
<ul>
<li>[CONZOLE] > -TOP SECRET- . PAGE //stripslash 1.3.8.9.84.113.21.73</li>
<li>[CONZOLE] > -TOP SECRET- . PAGE //stripslash 1.4.8.9.84.113.21.74</li>
<li>[CONZOLE] > -TOP SECRET- . PAGE //stripslash 1.5.8.9.84.113.21.75</li>
<li>[CONZOLE] > -TOP SECRET- . PAGE //stripslash 1.6.8.9.84.113.21.76</li>
<li>[CONZOLE] > -TOP SECRET- . PAGE //stripslash 1.7.8.9.84.113.21.77</li>
</ul>
</div>
</body>
<script src="wow.js"></script>
</html>
I just thought, is there any possible way, to make custom cursor, that works on microsoft edge? On my website, i used this:
body{ cursor: url(cursor.png), pointer;}
but in microsoft edge, it is not working...
Any ideas how to solve this?/Is there any other way?
So.... after small recode, my website looks like this, see the fiddle and try, it is not working yet...
This property is not supported yet : http://caniuse.com/#search=cursor
This property is now supported : caniuse.com:cursor:url()
As Charaf mentioned: the property isn't yet supported in Edge. If your project requires a solution, you can sort of mimic the behavior with JavaScript.
JavaScript:
if(!CSS.supports('cursor', 'url(cursor.png), pointer')) {
var myCursor = document.createElement('img');
myCursor.src = 'cursor.png';
myCursor.style.position = 'absolute';
document.body.appendChild(myCursor);
document.addEventListener('mousemove', function(e) {
myCursor.style.left = e.pageX+'px';
myCursor.style.top = e.pageY+'px';
}, false);
}
I made a library called CursorJS for you. You can check it out here. If you scroll to the bottom of the JavaScript code, you can find initializing code:
/* Enable lib with cursor image src */
CursorJS.enable('http://files.softicons.com/download/toolbar-icons/plastic-mini-icons-by-deleket/png/32x32/Cursor-01.png');
CursorJS.addEl(document.querySelector('.myElement1'));
CursorJS.addEl(document.querySelector('.myElement3'));
In your case just do the following:
/* Enable lib with cursor image src */
CursorJS.enable('./cursor.png');
CursorJS.addEl(document.body);
Customization
CursorJS has a mouseOffset variable. It repesents difference of mouse position and position of image. For example, if I set it to
mouseOffset: {
x: 50,
y: 50
},
The mouse will be 50px off. The reason why I made this variable is that custom mouse was kind of "blinking", try to set it to {x:1,y:1} ;)
Live example
var CursorJS = {
img: new Image(),
els: [],
mouseOffset: {
x: 5,
y: 5
},
addedImg: false,
checkForIE: function() {
return (/MSIE/i.test(navigator.userAgent)
|| /rv:11.0/i.test(navigator.userAgent));
},
setDisplay: function() {
this.img.style.display =
this.els.indexOf(true) > -1 ? null : 'none';
},
getMouseCoords: function(e) {
var mx = 0, my = 0;
if (this.checkForIE())
mx = event.clientX + document.body.scrollLeft,
my = event.clientY + document.body.scrollTop;
else
mx = e.pageX,my = e.pageY;
if (mx < 0) mx = 0;
if (my < 0) my = 0;
return [mx, my];
},
mouseOver: function(e, id) {
this.els[id] = true;
this.setDisplay();
var coords = this.getMouseCoords(e);
this.img.style.left =
(coords[0]+this.mouseOffset.x) + 'px';
this.img.style.top =
(coords[1]+this.mouseOffset.y) + 'px';
},
mouseOut: function(e, id) {
this.els[id] = false;
this.setDisplay();
},
mouseMove: function(e) {
var coords = this.getMouseCoords(e);
this.img.style.left =
(coords[0]+this.mouseOffset.x) + 'px';
this.img.style.top =
(coords[1]+this.mouseOffset.y) + 'px';
},
addEvent: function(el, name, func, bool) {
if (el == null || typeof name != 'string'
|| typeof func != 'function'
|| typeof bool != 'boolean')
return;
if (el.addEventListener)
el.addEventListener(name, func, false);
else if (el.attachEvent)
el.attachEvent('on' + name, func);
else
el['on' + name] = func;
},
addEl: function(el) {
var evts = ['over','out','move'],
id = this.els.length;
this.els.push(false);
this.el = el;
this.addEvent(el, 'mouseover', function(e) {
this.mouseOver(e, id) }.bind(this), false);
this.addEvent(el, 'mouseout', function(e) {
this.mouseOut(e, id) }.bind(this), false);
this.addEvent(el, 'mousemove', function(e) {
this.mouseMove(e) }.bind(this), false);
if (typeof el['style'] != 'undefined')
el.style.cursor = 'none';
},
enable: function(src) {
this.img.src = src;
this.img.style.display = 'none';
this.img.style.position = 'absolute';
this.img.style.cursor = 'none';
this.addEvent(this.img, 'mousemove', function(e) {
this.mouseMove(e) }.bind(this), false);
if (!this.addedImg)
document.body.appendChild(this.img),
this.addedImg = true;
}
}
/*** INITIALIZE ***/
CursorJS.enable('http://files.softicons.com/download/toolbar-icons/plastic-mini-icons-by-deleket/png/32x32/Cursor-01.png');
CursorJS.addEl(document.querySelector('.myElement1'));
CursorJS.addEl(document.querySelector('.myElement3'));
.myElement1, .myElement2, .myElement3 {
width: 150px;
height: 150px;
border: 1px solid gray;
display: inline-block;
}
<div class="myElement1">added</div>
<div class="myElement2">not added</div>
<div class="myElement3">added</div>
Hope that worked! Have a nice day :)
Here is a Plunker sketch of my problem.
The relevant code, containing the Polymer template and its invocation:
<link rel="import"
href="http://www.polymer-project.org/1.0/components/polymer/polymer.html">
<dom-module id="polymer-d3-component">
<template>
<style>
#monthChart .line {
stroke: rgb(247, 150, 29);
stroke-width: 2;
fill: none;
}
#monthChart .axis {
shape-rendering: crispEdges;
}
#monthChart .x.axis line {
stroke: rgba(88, 89, 93, .12);
}
#monthChart .x.axis .minor {
stroke-opacity: .5;
}
#monthChart .x.axis path {
display: none;
}
#monthChart .y.axis line, .y.axis path {
fill: none;
stroke: rgba(88, 89, 93, .5);
}
#monthChart .axis path,
#monthChart .axis line {
fill: none;
stroke: rgba(88, 89, 93, .3);
shape-rendering: crispEdges;
}
#monthChart .axis text {
font: 10px sans-serif;
fill: rgba(88, 89, 93, .5);
}
</style>
<div id="monthChart"></div>
</template>
<script>
Polymer({
is: "polymer-d3-component",
ready: function() {
var m = [20, 20, 20, 20];
var w = 850 - m[1] - m[3];
var h = 400 - m[0] - m[2];
var data=[24509, 19466, 18004, 18381, 17312, 19926, 24761, 24815, 24333, 29117, 24527, 17478];
function formatCurrency (d) {
return "$" + d;
}
var xLabels = d3.time.scale().domain([new Date(2013, 0, 1), new Date(2013, 11, 31)]).range([0, w]);
var x = d3.scale.linear().domain([0, data.length]).range([0, w]);
var y = d3.scale.linear().domain([0, d3.max(data)]).range([h, 0]);
var line = d3.svg.line()
.x(function(d, i) {
return x(i);
})
.y(function(d) {
return y(d);
})
var graph = d3.select(this.$.monthChart).append("svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("g")
.attr("transform", "translate(" + 120 + "," + m[0] + ")");
var xAxis = d3.svg.axis().scale(xLabels).ticks(d3.time.months).tickFormat(d3.time.format("%B")).tickSize(-h).tickSubdivide(true);
graph.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis);
var yAxisLeft = d3.svg.axis().scale(y).ticks(7).tickFormat(formatCurrency).orient("left");
graph.append("g")
.attr("class", "y axis")
.attr("transform", "translate(-25,0)")
.call(yAxisLeft);
graph.append("path")
.attr("d", line(data))
.attr('class', 'line');
}
})
</script>
</dom-module>
The SVG is wrong but also the styles are not being applied, as can be seen by the shapes being all black and many are not drawn correctly. If I take the SVG code and manually put it directly in the Polymer component, it works fine.
What might be going on?
Polymer applies styles when the template is rendered to a DOM, so DOM nodes appended by libraries later (e.g. in ready) are not styled. This is described in the manual here.
The fix is to call—
this.scopeSubtree(this.$.monthChart, true);
—at the beginning of ready. This tells Polymer to watch the given subtree for changes and apply the given styles whenever nodes appended to it by other libraries, such as D3.
Here's a fork of your Plunk with that.
I'm trying to make an "image mosaic" that consists mostly of images of the same size, and some of them the double height.
They all should align neatly like this:
To make automatic generation of those mosaic as easy as possible, I thought floating them would be the best option. Unfortunately, the big block causes the following ones to flow behind it, but not before:
What can I do - apart from manually positioning them - to get the images to the place I want, and still have it easy to automatically create likewise layouts?
The code I'm currently using is :
FIDDLE
HTML :
<div class="frame">
<div id="p11" class="img">1.1</div>
<div id="p12" class="img h2">1.2</div>
<div id="p13" class="img">1.3</div>
<div id="p21" class="img">2.1</div>
<div id="p22" class="img">2.2</div>
</div>
CSS :
.frame {
background-color: blue;
border: 5px solid black;
width: 670px;
}
.img {
width: 200px;
height: 125px;
background-color: white;
border: 1px solid black;
float: left;
margin: 10px;
}
.h2 {
height: 272px;
}
You need to use Javascript to achieve this effect, I had to do that once and I used http://masonry.desandro.com/ -- worked well!
Pure CSS Solution
Tested in Firefox, IE8+ (IE7 looks like it would need to be targeted to add a top margin added to 2.1 because it overlaps 1.1). See fiddle. This assumes .h2 is the middle div (as your example). If left most div it should not need any change. If right most, you would need to expand the negative margin to also include the third div following.
.h2 + div {
float: right;
margin: 10px 14px 10px 0; /*14px I believe also has to do with borders */
}
.h2 + div + div {
margin-left: -434px; /*need to account for borders*/
clear: right;
}
You can use a column layout like this:
http://jsfiddle.net/KKUZL/
I don't know if that will conflict with your automation process though....
I realize this is not a CSS-only solution, but for what it's worth (JSFiddle):
HTML:
<div id='container'></div>
CSS:
html, body {
margin:0px;
padding:0px;
height:100%;
}
body {
background-color:#def;
}
#container {
margin:0px auto;
width:635px;
min-height:100%;
background-color:#fff;
box-shadow:0px 0px 5px #888;
box-sizing:border-box;
overflow:auto;
}
.widget {
float:left;
box-sizing:border-box;
padding:10px 10px 0px 0px;
}
.widget > div{
height:100%;
box-sizing:border-box;
color:#fff;
font-size:3em;
text-align:center;
padding:.5em;
overflow:hidden;
}
.widget > div:hover {
background-color:purple !important;
}
JS:
////////////////////////////////////////
// ASSUMPTIONS
//
var TWO_COLUMN_WIDGET_COUNT = 1;
var ONE_COLUMN_WIDGET_COUNT = 15;
var NUMBER_OF_COLUMNS = 2;
////////////////////////////////////////
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var colorFactory = (function () {
var colors = [
'#CC9A17',
'#9B2C16',
'#1A8B41',
'#D97114',
'#3B9EE6'];
var index = 0;
return function () {
if (index > 4) {
index = 0;
}
return colors[index++];
}
})();
function widgetFactory(columnSpan) {
return {
'height': rand(10, 30) * 10,
'width': 100 * columnSpan / NUMBER_OF_COLUMNS,
'columnSpan': columnSpan,
'color': colorFactory()
}
}
function getWidgets() {
var widgets = [];
for (var i = 0; i < TWO_COLUMN_WIDGET_COUNT; i++) {
widgets.push(widgetFactory(2));
}
for (var i = 0; i < ONE_COLUMN_WIDGET_COUNT; i++) {
widgets.push(widgetFactory(1));
}
return widgets;
}
function getHighestOffset(offsets){
}
function getHighestSlot(offsets, numOfColumns){
}
$(document).ready(function () {
var container = $('#container');
var widgets = getWidgets();
var col1 = Math.floor(container[0].offsetLeft);
var col2 = Math.floor(container[0].clientWidth / 2 + container[0].offsetLeft);
var offsets = {};
offsets[col1] = 0;
offsets[col2] = 0;
var newLine = true;
for (var i = 0; i < widgets.length; i++) {
var w = widgets[i];
var marginTop = 0;
if (offsets[col1] < offsets[col2]) {
marginTop = (offsets[col2] - offsets[col1]) * -1;
}
if(offsets[col1] <= offsets[col2] || w.columnSpan == 2){
newLine = true;
}
var margin = 'margin-top:' + marginTop + 'px;';
var height = 'height:' + w.height + 'px;';
var color = 'background-color:' + colorFactory() + ';';
var width = 'width:' + w.width + '%;';
var padding = newLine ? "padding-left:10px;" : "";
var component = $('<div class="widget" style="' + padding + margin + height + width + '"><div style="' + color + '">' + i + '</div></div>');
component.appendTo(container);
var c = component[0];
var index = 0;
var minOffset = null;
for(var p in offsets){
if(minOffset == null || offsets[p] < minOffset){
minOffset = offsets[p];
}
if(p == Math.floor(c.offsetLeft)){
index = 1;
}
if(index > 0 && index <= w.columnSpan){
offsets[p] = c.offsetTop + c.offsetHeight;
index++;
}
}
newLine = minOffset >= offsets[col1];
}
});