除刻度刻度以适应容器宽度?

时间:2019-04-18 12:50:21

标签: d3.js

我想制作一个在大屏幕上将x timescale(tick?)划分为一个月(31天)或在小屏幕上划分为1周(7天)的时间轴。 我希望它集中在视图中心的月末。

这种运球设计是我想以某种方式实现的。

enter image description here

我从这里https://github.com/d3/d3-zoom/issues/57#issuecomment-246434951

复制一些代码

但仍然无法使刻度线平均适应屏幕大小

这是我到目前为止所得到的。

import d3 from 'd3'
import moment from 'moment'

window.d3 = d3

export default (container, dataset, options) => {
  const containerWidth = container.getBoundingClientRect().width
  const containerHeight = container.getBoundingClientRect().height
  const timelineHeight = 4

  const {
    startAt,
    endAt,
  } = options

  const svg = d3.select(container)
    .style('position', 'relative')
    .append('svg')
    .style('width', '100%')
    .style('height', containerHeight)
    .style('position', 'absolute')
    .append('g')

  const svgContainer = d3.select(svg.node().parentNode)

  const timeScale = d3.scaleTime()
    .domain([startAt, endAt])
    .range([0, containerWidth])
    // .rangeRound([20, containerWidth - 20])
    .nice(d3.timeDay)

  const guideline = d3
    .axisBottom(timeScale)
    // .ticks(d3.timeDay)
    // .tickSize(containerHeight)

  const xAxis = d3
    .axisBottom(timeScale)
    .ticks(d3.timeDay)
    .tickSize(0)
    .tickFormat(d3.timeFormat('%Y.%_m.%_d'))

  const xScaleGroup = svg
    .append('g')
    .attr('class', 'xscale-group')

  // const guidelineGroup = xScaleGroup
  //   .append('g')
  //   .attr('class', 'guideline-group')
  //   .call(guideline)

  const xAxisGroup = xScaleGroup
    .append('g')
    .attr('class', 'xaxis-group')
    .call(xAxis)

  const timelineGroup = xScaleGroup
    .append('g')
    .attr('class', 'timeline-group')
    .style('transform', 'translateY(32px)')

  const timelineBgGroup = timelineGroup
    .append('g')
    .attr('class', 'timeline-bg-group')

  const timelineBgRect = timelineBgGroup
    .append('rect')
    .attr('width', containerWidth)
    .attr('height', timelineHeight)
    .attr('fill', 'red')

  const eventGroup = timelineGroup
    .selectAll('.event-group')
    .data(dataset)
    .enter()
    .append('g')
    .attr('id', (d, i) => 'event-group-' + i)
    .attr('class', 'event-group')
    .style('transform', d => `translate(${timeScale(d.startAt)}px, 0px)`)

  const eventCircle = eventGroup
    .append('circle')
    .attr('r', 16)
    .attr('fill', ({ color }) => color)
    .attr('stroke', 'white')
    .attr('stroke-width', 2)
    // .attr('filter', 'url(#circle-shadow)')
    .attr('id', (d, i) => 'circle-' + i)
    .each(function (d) {
      d.circle = this
    })

  const zoom = d3.zoom()
    // .scaleExtent([1, 32])
    // .translateExtent([[0, 0], [containerWidth, containerHeight]])
    // .extent([[0, 0], [containerWidth, containerHeight]])
    .on('zoom', onZoom)

  svgContainer
    .call(zoom)
    .on('dblclick.zoom', null)

  const now = new Date()
  const startOf = moment().startOf('month').toDate()
  const endOf = moment().endOf('month').toDate()
  var k = containerWidth / (timeScale(endOf) - timeScale(startOf))
  var tx = containerWidth / 2 - k * timeScale(now)
  // var tx = -timeScale(startOf)
  var t = d3.zoomIdentity.translate(tx, 0).scale(k)

  svgContainer.call(zoom.transform, t)

  function onZoom() {
    const t = d3.event.transform, xt = t.rescaleX(timeScale)
    xAxisGroup.call(xAxis.scale(xt))
    // guidelineGroup.call(guideline.scale(xt))
    eventGroup.style('transform', ({ startAt }) => `translateX(${xt(startAt)}px)`)
  }
}

enter image description here

我想从2019.4.1开始

0 个答案:

没有答案