react实现标尺刻度
实现标尺刻度的方法
在React中实现标尺刻度可以通过多种方式完成,以下是几种常见的方法:
使用CSS和Flexbox布局
通过CSS的Flexbox布局可以轻松实现水平或垂直标尺刻度。定义一个容器元素,使用Flexbox均匀分布刻度线。
import React from 'react';
import './Ruler.css';
const Ruler = ({ length, orientation }) => {
const ticks = Array.from({ length }, (_, i) => i);
return (
<div className={`ruler ${orientation}`}>
{ticks.map((tick) => (
<div key={tick} className="tick">
{tick % 5 === 0 && <span className="label">{tick}</span>}
</div>
))}
</div>
);
};
export default Ruler;
.ruler {
display: flex;
background: #f0f0f0;
padding: 5px;
}
.ruler.horizontal {
flex-direction: row;
height: 30px;
}
.ruler.vertical {
flex-direction: column;
width: 30px;
}
.tick {
flex: 1;
position: relative;
}
.tick:after {
content: '';
position: absolute;
background: #333;
}
.horizontal .tick:after {
width: 1px;
height: 10px;
bottom: 0;
}
.vertical .tick:after {
width: 10px;
height: 1px;
right: 0;
}
.label {
position: absolute;
font-size: 10px;
}
.horizontal .label {
bottom: 15px;
}
.vertical .label {
right: 15px;
}
使用SVG绘制标尺
SVG是绘制标尺的理想选择,因为它可以精确控制每个元素的位置和样式。
import React from 'react';
const SVGRuler = ({ width, height, isHorizontal }) => {
const ticks = [];
const majorTickLength = 15;
const minorTickLength = 10;
const tickSpacing = 10;
for (let i = 0; i < (isHorizontal ? width : height); i += tickSpacing) {
const isMajorTick = i % 50 === 0;
ticks.push(
isHorizontal ? (
<line
key={i}
x1={i}
y1={0}
x2={i}
y2={isMajorTick ? majorTickLength : minorTickLength}
stroke="#000"
strokeWidth="1"
/>
) : (
<line
key={i}
x1={0}
y1={i}
x2={isMajorTick ? majorTickLength : minorTickLength}
y2={i}
stroke="#000"
strokeWidth="1"
/>
)
);
}
return (
<svg width={width} height={height}>
{ticks}
</svg>
);
};
export default SVGRuler;
使用Canvas绘制动态标尺
Canvas适合需要高性能或动态更新的标尺实现。
import React, { useRef, useEffect } from 'react';
const CanvasRuler = ({ width, height, isHorizontal }) => {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, width, height);
const tickSpacing = 10;
const majorTickLength = 15;
const minorTickLength = 10;
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
if (isHorizontal) {
for (let i = 0; i < width; i += tickSpacing) {
const isMajorTick = i % 50 === 0;
ctx.beginPath();
ctx.moveTo(i, 0);
ctx.lineTo(i, isMajorTick ? majorTickLength : minorTickLength);
ctx.stroke();
if (isMajorTick) {
ctx.font = '10px Arial';
ctx.fillText(i.toString(), i - 5, majorTickLength + 10);
}
}
} else {
for (let i = 0; i < height; i += tickSpacing) {
const isMajorTick = i % 50 === 0;
ctx.beginPath();
ctx.moveTo(0, i);
ctx.lineTo(isMajorTick ? majorTickLength : minorTickLength, i);
ctx.stroke();
if (isMajorTick) {
ctx.save();
ctx.translate(majorTickLength + 5, i + 5);
ctx.rotate(-Math.PI / 2);
ctx.font = '10px Arial';
ctx.fillText(i.toString(), 0, 0);
ctx.restore();
}
}
}
}, [width, height, isHorizontal]);
return <canvas ref={canvasRef} width={width} height={height} />;
};
export default CanvasRuler;
使用第三方库
对于更复杂的需求,可以考虑使用专门的库如react-ruler或react-measure。
import React from 'react';
import Ruler from 'react-ruler';
const App = () => {
return (
<div style={{ position: 'relative', width: '500px', height: '30px' }}>
<Ruler
width={500}
height={30}
direction="horizontal"
scale={1}
unit="px"
style={{ background: '#f5f5f5' }}
/>
</div>
);
};
export default App;
关键注意事项
- 性能优化:对于大量刻度,考虑使用虚拟滚动技术只渲染可见部分
- 响应式设计:确保标尺能适应不同屏幕尺寸
- 可访问性:为视力障碍用户添加适当的ARIA属性
- 交互功能:添加拖动、缩放等交互功能时要注意事件处理
以上方法可以根据具体需求选择使用,CSS方案适合简单静态标尺,SVG和Canvas适合需要更多自定义的场景,第三方库则能快速实现复杂功能。






