/** @format */ import * as d3 from 'd3'; import _ from 'lodash'; import React, { useEffect, useRef } from 'react'; import styled from 'styled-components'; const Box = styled.div` background-image: url('https://gt-toolbox.oss-cn-beijing.aliyuncs.com/gt-toolbox/e5d25869-0ad9-4611-8bba-afec05704a1f.png'); background-size: 100%; background-repeat: no-repeat; .light { } `; interface ProgressProps { size?: any; [key: string]: any; } const Progress = (props: ProgressProps) => { const { size, count, totalCount, innerStartBg = 'rgba(56, 68, 102, 0.6)', innerEndBg = 'rgb(0, 206, 151)', outerStartBg = 'rgb(0, 206, 151)', outerEndBg = 'rgb(0, 206, 151)', } = props; const styleBase = { height: 44, width: 120, }; const svgRef = useRef(null); const firstUpdate = useRef(true); useEffect(() => { if (firstUpdate.current) { firstUpdate.current = false; onDraw(true); } else { onDraw(false); } return () => { d3.select(svgRef.current) .selectAll('g') .remove(); }; }, [ size.width, size.height, count, totalCount, innerStartBg, innerEndBg, outerStartBg, outerEndBg, ]); function onDraw(flag: boolean) { const allWidth = size.width * 0.95; const bgData = d3.range(5, allWidth, size.width / 30); const LightData = d3.range( 5, (allWidth * count) / totalCount, size.width / 30, ); const colorBgScale = d3 .scaleLinear() .domain([0, size.width]) .range([outerStartBg, outerEndBg]); const colorScale = d3 .scaleLinear() .domain([0, size.width]) .range([innerStartBg, innerEndBg]); const svg = d3.select(svgRef.current); // 背景颜色条 svg .selectAll('.bg') .data(bgData) .enter() .append('g') .append('rect') .attr('class', 'bg') .attr('x', function(d: any) { return d; }) .attr('y', 6) .attr('width', size.width / 60) .attr('height', (42 / 375) * size.width - 10) .attr('fill', function(d: any) { return colorBgScale(d); }); // 填充颜色条 if (flag) { svg .selectAll('.light') .data(LightData) .enter() .append('g') .append('rect') .attr('class', 'light') .attr('x', function(d: any) { return d; }) .attr('y', 6) .attr('width', size.width / 60) .attr('height', (42 / 375) * size.width - 10) .attr('fill', function(d: any) { return colorBgScale(d); }) .transition() .duration(100) .delay(function(d: any, i: number) { return i * 30; }) .ease(d3.easePolyInOut) .attr('fill', function(d: any) { return colorScale(d); }); } else { svg .selectAll('.light') .data(LightData) .enter() .append('g') .append('rect') .attr('class', 'light') .attr('x', function(d: any) { return d; }) .attr('y', 6) .attr('width', size.width / 60) .attr('height', (42 / 375) * size.width - 10) .attr('fill', function(d: any) { return colorScale(d); }); } } const style = _.merge(styleBase, size); return ( ); }; Progress.themeUpdate = function(params: any) { return { outerBg: params.primaryColor, innerBg: params.thirdColor, }; }; export default Progress;