var width = 960, height = 840 var projection = d3.geo.azimuthalEquidistant() .scale(width / 5) .translate([0, 0]) .rotate([-18 * 15, -66.56]) var canvas = d3.select("body").append("canvas").attr("id", "canvas") var ctx = canvas.node().getContext("2d") var offScreenCanvas = document.createElement('canvas') var offCtx = offScreenCanvas.getContext('2d') function getRetinaRatio() { var devicePixelRatio = window.devicePixelRatio || 1 var backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1 return devicePixelRatio / backingStoreRatio } var ratio = getRetinaRatio() var scaledWidth = width * ratio var scaledHeight = height * ratio canvas.node().width = scaledWidth canvas.node().height = scaledHeight canvas .style("width", width + 'px') .style("height", height + 'px') offScreenCanvas.width = scaledWidth offScreenCanvas.height = scaledHeight ctx.scale(ratio, ratio) ctx.translate(width / 2, height / 2) function addZodiacName(data) { var x1 = 0, y1 = -data.y / Math.sin(Math.atan2(data.y, data.x)) ctx.save() ctx.rotate(Math.atan2(data.y, data.x) + Math.PI / 2 ) ctx.textAlign = "center" ctx.font = "12px sans-serif" ctx.fillStyle = "white" ctx.fillText(data.name, x1, y1) ctx.restore() } function distance(x,y) { return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) } function drawLine(line) { ctx.strokeStyle = (line.zodiac) ? '#f2f237':'white' ctx.lineWidth = (line.zodiac) ? 0.8 : 0.4 ctx.beginPath() ctx.moveTo(line.line[0][0], line.line[0][1]) ctx.lineTo(line.line[1][0], line.line[1][1]) ctx.stroke() } function drawStar(star) { ctx.fillStyle = star.color ctx.beginPath() ctx.moveTo(star.projection[0], star.projection[1]) ctx.arc(star.projection[0], star.projection[1], star.radius, 0 ,Math.PI * 2 ,true) ctx.fill() } function clearCtx(){ ctx.clearRect(-width / 2, -height / 2, width, height) } function changeColor(imageData, color){ var px = imageData.data var rgb = d3.rgb(color) for (var x = 0; x < px.length; x += 4){ if (px[x + 3]) { px[x] = rgb.r px[x + 1] = rgb.g px[x + 2] = rgb.b px[x + 3] *= 15 } } } function getImage(ctx){ return ctx.getImageData(0, 0, scaledWidth, scaledHeight) } d3.json("/erohinaelena/raw/ec635d68e8bf55586d40/starData.json", function(error, data) { var begin = performance.now() var constellationLines = [] var constellationStars = [] var zodiacNames = [] data.forEach(function (constellation) { var name = constellation.name var projections = constellation.stars.map(function (star) { var p = projection([star.ra, star.dec]) var out = (distance(p[0], p[1]) > width / 2.5) return { color: star.color, mag: star.mag, radius: Math.pow(1.2, 3 - star.mag), projection: p, out: out } }) var x = d3.mean(projections, function (d) { return d.projection[0] = -d.projection[0] }) var y = d3.mean(projections, function (d) { return d.projection[1] }) projections = projections.filter(function (star) { return !star.out && star.mag <= 6 }) if (distance(x, y) < width / 3 || constellation.zodiac){ var lines = constellation.lines.map(function (line) { var p1 = projection([line.ra1, line.dec1]) var p2 = projection([line.ra2, line.dec2]) p1[0] = -p1[0] p2[0] = -p2[0] var out = distance(p1[0], p1[1]) > width / 3 return {line: [p1, p2], zodiac: constellation.zodiac, out: out} }) lines = lines.filter(function (line) { return !line.out || line.zodiac }) constellationLines.push(lines) } constellationStars.push(projections) if (constellation.zodiac) zodiacNames.push({ name: name, x: x, y: y }) }) constellationLines.forEach(function(lines){ lines.forEach(drawLine) }) var linesLayer = getImage(ctx) clearCtx() constellationStars.forEach(function(projections){ projections.forEach(drawStar) }) var starsLayer = getImage(ctx) stackBlurCanvasRGBA('canvas', 0, 0, width, height, 1) var bgStarsLayer = getImage(ctx) changeColor(bgStarsLayer, '#000313') clearCtx() zodiacNames.forEach(addZodiacName) var namesLayer = getImage(ctx) stackBlurCanvasRGBA('canvas', 0, 0, width, height, 3) var bgNamesLayer = getImage(ctx) changeColor(bgNamesLayer, '#000313') clearCtx() ctx.scale(1 / ratio, 1 / ratio ) offCtx.putImageData(linesLayer, 0, 0) ctx.drawImage(offScreenCanvas, -scaledWidth / 2, -scaledHeight / 2) offCtx.putImageData(bgStarsLayer, 0, 0) ctx.drawImage(offScreenCanvas, -scaledWidth / 2, -scaledHeight / 2) offCtx.putImageData(starsLayer, 0, 0) ctx.drawImage(offScreenCanvas, -scaledWidth / 2, -scaledHeight / 2) offCtx.putImageData(bgNamesLayer, 0, 0) ctx.drawImage(offScreenCanvas, -scaledWidth / 2, -scaledHeight / 2) offCtx.putImageData(namesLayer, 0, 0) ctx.drawImage(offScreenCanvas, -scaledWidth / 2, -scaledHeight / 2) var fps = 'fps' var frames = 0 function animate(){ window.requestAnimationFrame(animate) frames++ } animate() setInterval(function () { fps = frames / 10 + ' fps' console.log(fps) frames = 0 }, 10000) setTimeout(function () {console.log(performance.now() - begin,'ms')}) })