var width = 960, height = 680 var bgColor = "#ffdcdc" var projection = d3.geo.azimuthalEquidistant() .scale(width / 4) .translate([0, 0]) .rotate([180, 270]) // полярная звезда в центре var center = [width / 2, height / 4] //canvas var canvas = d3.select("body").append("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 ].reduce(function(a, b) { return a || b }) 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 offCtx.scale(ratio, ratio) offCtx.translate(center[0], center[1]) //svg var sliderWidth = width - 2 * 20 var x = d3.scale.linear() .domain([-1, 1]) .range([0, sliderWidth]) .clamp(true); var topColor = d3.scale.linear() .domain([-1, -0.9, 0, 0.9, 1]) .range(["#6767c8", "#6767c8","#000313", "#6890B1", "#6890B1"]); var bottomColor = d3.scale.linear() .domain([-1, -0.9, 0, 0.9, 1]) .range(["#F39217", "#6767c8","#000313", "#6890B1", "#D49A83"]); var sliderSvg = d3.select('body').append('svg') .attr('width', width) .attr('height', 30) .append('g') .attr('transform', 'translate(20,10)') var sliderG = sliderSvg.append('g'); sliderG .attr('transform', 'translate(0,5)') .attr('class', 'axis') .call(d3.svg.axis() .scale(x) .orient('bottom') .tickSize(20, 20) .tickValues('') ); var brush = d3.svg.brush() .x(x) .extent([0, 0]) .on('brush', brushed); var slider = sliderSvg.append('g') .call(brush); var handle = slider .append('circle') .attr('class', 'handle') .attr('transform', 'translate(0,10)') .attr('r', 9) .attr('cy', -5) .attr('cx', 0); slider .select('.background') .attr('height', 40); function brushed() { if (d3.event.sourceEvent) { // not a programmatic event targetValue = x.invert(d3.mouse(this)[0]); move(); } else { var v = brush.extent()[0]; handle.attr('cx', x(v)); update(v); } } function move() { if (move.moving) return; move.moving = true; d3.timer(function () { currentValue = targetValue; slider.call(brush.extent([currentValue, currentValue])) .call(brush.event); return !(move.moving = currentValue !== targetValue); }); } move.moving = false; function update(val) { bgColor = ctx.createLinearGradient(0, 0, 0, height); bgColor.addColorStop(0, topColor(val)) bgColor.addColorStop(1, bottomColor(val)) stars = constellationStars.map(function(projections){ var s = [] projections.map(function (star) { var opacity = star.currentOpacity(1 - Math.abs(val)) star.rgba = 'rgba(' + star.rgb.r + ',' + star.rgb.g + ',' + star.rgb.b + ',' + opacity + ')' if (opacity) s.push(star) }) return s }) } function clearCtx(){ offCtx.clearRect(-center[0], -center[1], width, height) ctx.clearRect(0, 0, scaledWidth, scaledHeight) } function drawSquareStar(star){ offCtx.fillStyle = star.rgba offCtx.fillRect(star.projection[0], star.projection[1], 1, 1) } var constellationStars = [] var stars = [] d3.json("/erohinaelena/raw/ec635d68e8bf55586d40/starData.json", function(error, data) { var starsMag = [] data.map(function(c){ c.stars.map(function(star){ starsMag.push(star.mag) }) }) var minMaxMag = d3.extent(starsMag) console.log(minMaxMag) var opacityScale = d3.scale.linear() .domain([minMaxMag[0], 6, minMaxMag[1]]) .range([1, 0.4, 0.2]) data.forEach(function (constellation) { var projections = constellation.stars.map(function (star) { var opacity = opacityScale(star.mag) var D = .1 var Y = (d3.scale.linear() .domain([minMaxMag[0], 6, minMaxMag[1]]) .range([D, 0.8, 1 - D]))(star.mag) var currentOpacity = d3.scale.linear() .domain([0, Y - D, Y + D, 1]) .range([0, 0, opacity, opacity]) var p = projection([-star.ra, star.dec]) if (star.mag < 0) console.log(star.mag, constellation.name, ' opacity: ' + opacity) return { rgb: d3.rgb(star.color), opacity: opacity, currentOpacity: currentOpacity, projection: [Math.round(p[0]), Math.round(p[1])] } }) constellationStars.push(projections) }) var angle = 0 var fps = 0 var frames = 0 update(-1) function draw () { begin = performance.now() frames++ clearCtx() offCtx.fillStyle = bgColor offCtx.fillRect(-center[0], -center[1], width, height) offCtx.fillStyle = '#fff' offCtx.fillText(fps + ' fps', -center[0] + 10, -center[1] + 50) angle += 0.0001 offCtx.save() offCtx.rotate(angle) stars.forEach(function(projections){ projections.forEach(drawSquareStar) }) offCtx.restore() ctx.drawImage(offScreenCanvas, 0, 0); } function animate(){ window.requestAnimationFrame(animate) draw() } animate() setInterval(function () { fps = frames / 10 console.log(fps + ' fps') frames = 0 }, 10000) setTimeout(function () {console.log(performance.now() - begin,'ms') }) })