>  기사  >  웹 프론트엔드  >  SVG를 사용하여 HTML로 추세 차트를 그리는 방법을 설명하는 기사(코드 공유)

SVG를 사용하여 HTML로 추세 차트를 그리는 방법을 설명하는 기사(코드 공유)

奋力向前
奋力向前앞으로
2021-08-26 09:58:082793검색

이전 글 "Javascript의 Reflect 내장 객체에 대한 간략한 분석(자세한 코드 설명)"에서 JS의 Reflect 내장 객체에 대해 소개해 드렸습니다. 다음 기사에서는 SVG를 사용하여 트렌드 차트를 그리는 방법을 소개합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

SVG를 사용하여 HTML로 추세 차트를 그리는 방법을 설명하는 기사(코드 공유)

먼저 viewBox의 용도, 즉 뷰의 크기를 비례적으로 조정하는 것에 대해 이야기해 보겠습니다. 그래픽을 사용하여 viewBox是干嘛的,就是按比例缩放视图的。用图形来表示

<svg width="300" height="200" style="border:1px solid #ddd">
  <rect width="80" height="70" style="fill:#BDC9FF"></rect>
</svg>


加上viewBox="0,0,80,70"

<svg width="300" height="200" style="border:1px solid #ddd" viewBox="0,0,80,70">
  <rect width="80" height="70" style="fill:#BDC9FF"></rect>
</svg>


当然还有可以配合preserveAspectRatio属性来使用,其取值有xMin,xMid,xMax,yMin,yMid,yMax,meet(保持纵横比缩放),slice(保持纵横比同时比例小的方向放大填满 viewport) 就是缩放的时候是 起始和结束的依据点。如:preserveAspectRatio="xMidyMin meet"就是 以x,y最小值为起点保持比例缩放

上面说的是试图缩放,接下来要说的是:如何把大象放进冰箱,需要几步?

首先说明我要干什么:根据数据画行情走势图。就是画曲线,只画曲线,所以不用canvas,采用SVGpolyline来实现,相对较容易的多了。

最终要得到如下:

SVG를 사용하여 HTML로 추세 차트를 그리는 방법을 설명하는 기사(코드 공유)

拿到的数据是这样的:

BTC:[6612.775,6610.77,6585.72,6590.54,6587.38,6570.685,6565.215,6561.175,6557.735,6585.975,6601.18,6620,6596.5,6594.82,6594.5,6595.245,6599.005,6586.52,6582.12,6600.805,6614.515,6617.725,6614,6605.97,6631.715,6644.725,6596.355,6586.575,6594.175,6597.23,6592.285,6586.33,6579.57,6589.08,6576.42,6582.405,6609.89,6596.29,6586.145,6604.79,6594.375,6583.645,6580.32,6589.915,6594.555,6583.585,6599.6,6599.345,6572.185,6495.02,6476.98,6484.14,6509.8,6508.965,6479.21,6486.7,6463.08,6465.765,6467.155,6481.5,6528.43,6552.2,6566.19,6559.015,6522.25,6558.81,6573.42,6578.535,6593.305,6605.88,6611.695,6613.765,6611.765,6595.21,6601.5,6583.095,6575.155,6549.715,6590.31,6594.51,6617.565,6623.98,6637.5]

ETH:[523.05,520.625,516.555,517.03,516.84,515.375,513.44,510.015,508.075,512.7,514.175,515.915,511.13,510.36,508.24,509.325,511.885,511.71,511.965,514.45,517.81,519.87,519.495,518.035,520.435,522.44,515.38,514.225,515.51,516.16,516.265,514.755,514.165,515.605,515.105,513.76,517.73,517.15,514.695,520.09,519.93,521.21,521.42,521.865,526.23,526.26,528.475,529.21,522.5,517.5,515.31,515.07,518.815,518.935,514.56,516.19,511.925,516.505,517.85,522.03,532.255,537.33,538.505,534.74,530.345,536.19,535.55,538.09,543.155,544.39,549.165,543.73,532.845,532.485,530.815,529.42,529.945,525.42,532.49,535.26,536.9,534.32,539.065]

BCT:[5.7627,5.7536,5.7301,5.6882,5.6901,5.6759,5.6588,5.6724,5.7128,5.7375,5.7605,5.7543,5.7301,5.7298,5.7324,5.7121,5.7226,5.71,5.7025,5.7664,5.8049,5.8064,5.7976,5.7972,5.821,5.8486,5.7901,5.7303,5.7405,5.7783,5.7676,5.7358,5.721,5.7361,5.7149,5.7257,5.8168,5.8,5.7458,5.8002,5.7591,5.75,5.6963,5.6838,5.6716,5.6577,5.6724,5.6828,5.6638,5.6113,5.5479,5.5209,5.5457,5.5935,5.5685,5.5767,5.5376,5.5209,5.5,5.5,5.5751,5.659,5.6563,5.6715,5.6,5.6267,5.6437,5.6525,5.6678,5.6903,5.7346,5.7455,5.7435,5.7296,5.7485,5.665,5.6473,5.5814,5.635,5.6435,5.6616,5.6861,5.745]

没错,全都是y坐标数值。要利用这些数值在75*26 的(舞台或场景)视图上画走势图,也就是y坐标最大值为26x 坐标最大值为 75

那么问题来了: 

1)只有y坐标数组,没有x坐标,如何画曲线呢? 这个可以不用考虑,因为是画满画布,xy坐标默认为 00,所以x坐标数组为 0,1,2,3....75,y 坐标数组为 0,1,2,3...26

y坐标数组长度刚好为75组的情况下,默认画满画布,显然所给出的数据是大于75组的 

2)y坐标数组长度大于画布单位长度,x坐标如何取值? 刚好为75组的时候,x一次累加为1,大于75组的时候x坐标累加值为x=75 / BTC.length

这个时候xy坐标都知道了,那么开画吧,通过计算我们得到如下

<svg xmlns="http://www.w3.org/2000/svg" width="75" height="26">
  <polyline
    points="0 6612.775 0.9036144578313253 6610.77 1.8072289156626506 6585.72 2.710843373493976 6590.54 3.6144578313253013 6587.38 4.518072289156627 6570.685 5.421686746987952 6565.215 6.325301204819277 6561.175 7.228915662650602 6557.735 8.132530120481928 6585.975 9.036144578313253 6601.18 9.93975903614458 6620 10.843373493975905 6596.5 11.746987951807231 6594.82 12.650602409638557 6594.5 13.554216867469883 6595.245 14.457831325301209 6599.005 15.361445783132535 6586.52 16.26506024096386 6582.12 17.168674698795183 6600.805 18.072289156626507 6614.515 18.97590361445783 6617.725 19.879518072289155 6614 20.78313253012048 6605.97 21.686746987951803 6631.715 22.590361445783127 6644.725 23.49397590361445 6596.355 24.397590361445776 6586.575 25.3012048192771 6594.175 26.204819277108424 6597.23 27.108433734939748 6592.285 28.012048192771072 6586.33 28.915662650602396 6579.57 29.81927710843372 6589.08 30.722891566265044 6576.42 31.62650602409637 6582.405 32.530120481927696 6609.89 33.43373493975902 6596.29 34.337349397590344 6586.145 35.24096385542167 6604.79 36.14457831325299 6594.375 37.04819277108432 6583.645 37.95180722891564 6580.32 38.855421686746965 6589.915 39.75903614457829 6594.555 40.66265060240961 6583.585 41.56626506024094 6599.6 42.46987951807226 6599.345 43.373493975903585 6572.185 44.27710843373491 6495.02 45.180722891566234 6476.98 46.08433734939756 6484.14 46.98795180722888 6509.8 47.891566265060206 6508.965 48.79518072289153 6479.21 49.698795180722854 6486.7 50.60240963855418 6463.08 51.5060240963855 6465.765 52.409638554216826 6467.155 53.31325301204815 6481.5 54.216867469879475 6528.43 55.1204819277108 6552.2 56.02409638554212 6566.19 56.92771084337345 6559.015 57.83132530120477 6522.25 58.734939759036095 6558.81 59.63855421686742 6573.42 60.54216867469874 6578.535 61.44578313253007 6593.305 62.34939759036139 6605.88 63.253012048192716 6611.695 64.15662650602404 6613.765 65.06024096385536 6611.765 65.96385542168669 6595.21 66.86746987951801 6601.5 67.77108433734934 6583.095 68.67469879518066 6575.155 69.57831325301198 6549.715 70.48192771084331 6590.31 71.38554216867463 6594.51 72.28915662650596 6617.565 73.19277108433728 6623.98 74.0963855421686 6637.5 "
    style="stroke: rgb(189, 201, 255); stroke-width: 1; fill: none;"
  ></polyline>
</svg>

显然所得到的结果不是我们期待的,一片空白,看不到数据。为啥?

3)y坐标太大,超出场景最大范围,那么如何把大象放进冰箱呢? 缩放y的比例,然后向上垂直偏移坐标,塞回冰箱里,不让象的耳朵漏出来。把整体放大10

// 数据
//x坐标数组
let s = 750 / BTC.length;
//x起始坐标数组
let x = 0;
//y坐标最小值
let min = BTC.reduce((x, y) => (x > y ? y : x));
//y坐标最大值
let max = BTC.reduce((x, y) => (x > y ? x : y));
//缩放比例 max-min为曲线幅度
let rodio = 260 / (max - min);
// 此处的points 的值就是svg 都polyline 的points 属性的值
let points = "";
//统一处理y坐标,垂直向上偏移,也即是y坐标最高点归零
BTC.forEach((y) => {
  points += x + " " + (y - min) * rodio + " ";
  x += s;
});


🎜🎜 및 viewBox="0,0,80,70"🎜rrreee🎜
🎜🎜물론 값이 xMin, xMid, xMax, yMin, yMid, yMax, MeetpreserveAspectRatio 속성과 함께 사용할 수도 있습니다. >(가로세로 비율 조정 유지), 슬라이스(가로세로 비율을 유지하면서 뷰포트를 더 작은 방향으로 확대)는 조정 시 시작점과 끝점입니다. 예를 들어 preserveAspectRatio="xMidyMin Meet"는 비례 스케일링을 유지하기 위한 시작점으로 x, y의 최소값을 사용하는 것입니다🎜🎜위는 스케일링을 시도한 것입니다 , 그리고 다음으로 할 말은: 코끼리를 냉장고에 넣는 방법, 단계는 무엇입니까? 🎜🎜먼저 제가 하고 싶은 일을 설명하자면, 데이터를 기반으로 시장 동향 차트를 그리는 것입니다. 곡선만 그리는 것이므로 캔버스를 사용하는 것보다 SVG폴리라인을 사용하는 것이 훨씬 쉽습니다. 🎜🎜최종 결과는 다음과 같습니다. 🎜🎜 WeChat 스크린샷 _20210826094520.jpg🎜🎜얻은 데이터는 다음과 같습니다. 🎜rrreee🎜네, 모두 y 좌표 값입니다. 이 값을 사용하여 75*26의 (스테이지 또는 씬) 뷰에 트렌드 차트를 그리려면, 즉 y 좌표의 최대값 26입니다. x 좌표의 최대값은 75입니다. 🎜🎜그러면 다음 질문이 옵니다: 🎜🎜1) y 좌표 배열만 있고 x 좌표는 없습니다. 곡선을 그리는 방법은 무엇입니까? 캔버스를 채우고 x, y 좌표의 기본값은 0, 0이므로 이를 고려할 필요가 없습니다. 이므로 x 좌표 배열은 0, 1, 2, 3...75이고 y 좌표 배열은 0,1,2,3...26🎜🎜in입니다. y 좌표 배열의 길이가 정확히 75인 경우 기본적으로 캔버스가 채워집니다. 분명히 주어진 데이터는 75보다 큽니다. 그룹 🎜🎜2) y좌표 배열의 길이가 캔버스의 단위 길이보다 깁니다. x 좌표 값을 구하는 방법은 무엇입니까? 정확히 75 그룹인 경우, 75보다 큰 경우에는 <code>x가 한번에 1로 누적됩니다. code> 그룹, x 누적 좌표값은 x=75 / BTC.length🎜🎜 이때 x y 좌표를 알고 나면 시작합니다. 계산을 통해 다음과 같은 결과를 얻습니다. 🎜rrreee🎜 분명히 얻은 결과는 우리가 예상한 것과 다르며 비어 있고 데이터를 볼 수 없습니다. 왜? 🎜🎜3) y 좌표가 너무 커서 장면의 최대 범위를 초과합니다. 그렇다면 코끼리를 냉장고에 어떻게 넣을 수 있을까요? y 비율을 조정한 다음 좌표를 수직 위쪽으로 오프셋하고 코끼리 귀가 새어나오는 것을 방지하기 위해 냉장고에 다시 넣습니다. 전체를 10배 확대하면 다음을 얻을 수 있습니다 🎜


那么这个数据是如何计算出来的呢?

// 数据
//x坐标数组
let s = 750 / BTC.length;
//x起始坐标数组
let x = 0;
//y坐标最小值
let min = BTC.reduce((x, y) => (x > y ? y : x));
//y坐标最大值
let max = BTC.reduce((x, y) => (x > y ? x : y));
//缩放比例 max-min为曲线幅度
let rodio = 260 / (max - min);
// 此处的points 的值就是svg 都polyline 的points 属性的值
let points = "";
//统一处理y坐标,垂直向上偏移,也即是y坐标最高点归零
BTC.forEach((y) => {
  points += x + " " + (y - min) * rodio + " ";
  x += s;
});

最后还原缩放比例,得到最终想要的样子。

那么这个和viewbox有什么关联呢。

仔细观察,以上3组数据BTC,ETH,BTC,发现这些数据都不在同一个波段,显然这个时候 ,如果用viewbox来缩放视图不可取。当然非要用viewbox来处理也未尝不可,只是感觉很愚蠢。手动改变数值来达到目的更快而已。这样不管大象有多大,我们都能顺利的塞到冰箱里。

推荐学习:SVG视频教程Html视频教程

위 내용은 SVG를 사용하여 HTML로 추세 차트를 그리는 방법을 설명하는 기사(코드 공유)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 chuchur.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제