Skip to content

Instantly share code, notes, and snippets.

@shimizu
Last active July 27, 2016 03:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shimizu/e58f4fdc10ff29c1453d to your computer and use it in GitHub Desktop.
Save shimizu/e58f4fdc10ff29c1453d to your computer and use it in GitHub Desktop.
CSS 3D Line Chart
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>CSS 3D Line Chart</title>
<style>
html, body {
width: 100%;
height:100%;
}
#chart {
width: 900px;
height:500px;
transform: perspective( 600px ) rotateY( 45deg );
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
.grid .tick {
stroke: lightgrey;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}
.grid path {
stroke-width: 0;
}
</style>
</head>
<body>
<svg id="chart"></svg>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="http://shimz.me/module/thirdparty/stubJs.js"></script>
<script>
var width = 900;
var height = 300;
var margin = {top:0, left:280, bottom:0, right:0 }
//各種レイヤー要素を追加
var svg = d3.select('#chart')
var stage = svg.append("g")
var axis = stage.append("g")
var g = stage.append("g")
//ランダムにデータセットを作る
var indexSeries = d3.range(30).map(function(d){
return {x:d, y:Math.floor(Math.random()*5200)+1}
})
//スケール設定
var xScale = d3.scale.linear().domain([0, d3.max(indexSeries, function(d){ return d.x })]).range([margin.left, width])
var yScale = d3.scale.linear().domain([0, d3.max(indexSeries, function(d){ return d.y })]).range([height, 0])
//ライン生成関数を用意
var lineFunction = d3.svg.line()
.x(function(d){ return xScale(d.x) })
.y(function(d){ return yScale(d.y) })
//ステージを奥に向かって進むようにアニメーション
stage.attr("transform", "translate("+[0, 0]+")")
.transition()
.duration(6000)
.attr("transform", "translate("+[-400, 100]+")")
// svg filter要素を追加
var filter = stage.append("defs").append('filter')
.attr({
"id": "drop-shadow",
"width": "150%",
"height": "150%"
});
filter.append('feGaussianBlur')
.attr({
"in": "SourceAlpha",
"result": "blur",
"stdDeviation": "2"
});
filter.append('feOffset')
.attr({
"result": "offsetBlur",
"dx": 4,
"dy": 4
})
filter.append('feBlend')
.attr({
"in": "SourceGraphic",
"in2": "offsetBlur",
"mode": "normal"
});
// フィルター追加 end
//線グラフ追加
var line = g.append('path')
.attr("filter", "url(#drop-shadow)");
//線グラフのアニメーション
line.transition()
.duration(6000)
.attr('fill', 'none')
.attr('stroke', 'black')
.attrTween('d', getSmoothInterpolation);
//グリッド追加
axis.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat("")
)
axis.append("g")
.attr("class", "grid")
.call(make_y_axis()
.tickSize(-width, 0, 0)
.tickFormat("")
)
//軸追加
var xAxis = d3.svg.axis().scale(xScale)
.orient("bottom")
var yAxis = d3.svg.axis().scale(yScale)
.orient("left")
axis.append("g") // Add the X Axis
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
axis.append("g") // Add the Y Axis
.attr("class", "y axis")
.attr("transform", "translate("+margin.left+",0)")
.call(yAxis);
//パス用のカスタムトランジション
function getSmoothInterpolation() {
var interpolate = d3.scale.linear()
.domain([0,1])
.range([1, indexSeries.length + 1]);
return function(t) {
var flooredX = Math.floor(interpolate(t));
var interpolatedLine = indexSeries.slice(0, flooredX);
if(flooredX > 0 && flooredX < indexSeries.length) {
var weight = interpolate(t) - flooredX;
var weightedLineAverage = indexSeries[flooredX].y * weight + indexSeries[flooredX-1].y * (1-weight);
interpolatedLine.push({"x":interpolate(t)-1, "y":weightedLineAverage});
}
return lineFunction(interpolatedLine);
}
}
//xグリッド生成
function make_x_axis() {
return d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(40)
}
//yグリッド生成
function make_y_axis() {
return d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(20)
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment