将rem与d3一起使用(为了在不同比例下保持字体大小相似)

  • 本文关键字:字体 相似 一起 d3 rem css d3.js
  • 更新时间 :
  • 英文 :


当前首次使用d3&CSS的中端知识。

这是我将在这个问题中引用的代码笔,也是一个堆栈片段:

const padding = 30
const fakeData = [
[0, 0],
[100, 300],
[300, 250],
[500, 450]
]
function applyGraph(svg) {
// Setup the axes
const xScale = d3.scaleLinear()
.range([0 + padding, 200 - padding])
.domain([500, 0])
const yScale = d3.scaleLinear()
.range([0 + padding, 200 - padding])
.domain([0, 500])

const xAxis = d3.axisBottom(xScale).ticks(4)
const yAxis = d3.axisLeft(yScale).ticks(4)
svg.append('g')
.attr('class', 'axis-rem')
.attr('transform', `translate(0, ${200 - padding})`)
.call(xAxis)
svg.append('g')
.attr('class', 'axis-rem')
.attr('transform', `translate(${padding}, 0)`)
.call(yAxis)

// Plot some data
const line = d3.line()
.x(d => xScale(d[0]))
.y(d => yScale(d[1]))

svg.append('path')
.data([fakeData])
.attr('class', 'line-rem')
.attr('fill', 'none')
.attr('stroke', 'blue')
.attr('d', line)
}
var g1 = d3.select("#graph1")
var g2 = d3.select("#graph2")
applyGraph(g1)
applyGraph(g2)
.line-rem {
stroke-width: 0.4rem;
}
.axis-rem {
font-size: 0.6rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.6.1/d3.min.js"></script>
<svg 
id="graph1"
viewBox="0 0 200 200"
width="400" 
height="400"/>
<svg 
id="graph2"
viewBox="0 0 200 200"
width="200" 
height="200"/>

我有一个函数(组件(,它根据一些数据绘制d3图。此功能可在多个不同大小/比例的位置重复使用。我的目标是使文本和笔划宽度保持相同的大小,而不考虑SVG的缩放大小。

我最初的想法是使用rem单元,因为我以前听说过它们。我的理解是,这应该使尺寸相对于";根元素";。然而,即使在SVG中对stroke-widthfont-size使用了这些单元之后,文本和行看起来也具有不同的大小。

两个问题:

  1. 为什么会发生这种情况?是因为";根元素";是否重置为<svg>标签或类似内容
  2. 我将如何实现制作stroke-widthfont-size的目标(我不想在中硬编码一些px值(

这里和这里都有关于使用widthheightviewbox的有用答案。

较大的图表被"放大",因为相同的200x200坐标系被拉伸到较大的SVG上(400x400与200x200(。

如果您放弃viewBox并更改applyGraph以识别svgwidthheight,则图表将显示相同的字体和笔划宽度:

const padding = 30
const fakeData = [
[0, 0],
[100, 300],
[300, 250],
[500, 450]
]
function applyGraph(svg) {
// get dimensions of svg
const svgWidth = +svg.attr("width");
const svgHeight = +svg.attr("height");
// Setup the axes
const xScale = d3.scaleLinear()
.range([0 + padding, svgWidth - padding])
.domain([500, 0])
const yScale = d3.scaleLinear()
.range([0 + padding, svgHeight - padding])
.domain([0, 500])

const xAxis = d3.axisBottom(xScale).ticks(4)
const yAxis = d3.axisLeft(yScale).ticks(4)
svg.append('g')
.attr('class', 'axis-rem')
.attr('transform', `translate(0, ${svgHeight - padding})`)
.call(xAxis)
svg.append('g')
.attr('class', 'axis-rem')
.attr('transform', `translate(${padding}, 0)`)
.call(yAxis)

// Plot some data
const line = d3.line()
.x(d => xScale(d[0]))
.y(d => yScale(d[1]))

svg.append('path')
.data([fakeData])
.attr('class', 'line-rem')
.attr('fill', 'none')
.attr('stroke', 'blue')
.attr('d', line)
}
var g1 = d3.select("#graph1")
var g2 = d3.select("#graph2")
applyGraph(g1)
applyGraph(g2)
.line-rem {
stroke-width: 0.4rem;
}
.axis-rem {
font-size: 0.6rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.6.1/d3.min.js"></script>
<svg 
id="graph1"
width="400" 
height="400"/>
<svg 
id="graph2"
width="200" 
height="200"/>

最新更新