前端 不规则进度条,求好的思路?

image.png
这是一个水塔的svg,需求:
水面跟随进度上升下降
进度低于20时变红色,其余进度变绿色
整体尺寸不是固定的,跟随父布局大小

思路1:目前我的思路是根据进度,切10张水塔图,根据进度动态显示。但这增加包体积,感觉也有点粗暴。
思路2:用两张图上下放置,上面的水塔用clip-path根据进度切,但好像只能且固定大小,因为svg的path好像是固定的

目前没有更好的解决思路,各位大佬怎么看?

阅读 3.4k
4 个回答

感谢大家的解答,忘了说是小程序,小程序中稍微麻烦些,需要读取svg文件(需要用binary方式读取,不然iOS不显示),然后查找替换高度和颜色部位的值,再转为base64加载到image标签中。其实如果在web端,直接用变量控制即可。svg代码见文末。

大致效果:

动态高度的关键在于,查找并修改“蒙版”的高度,即下面的height="104",通过js控制变量即可实现动态高度。
至于修改颜色,查找fill="#06CB60",然后改成需要的颜色。

<rect width="64" height="104" transform="matrix(1 0 0 -1 28 106)" fill="white"/>
<path d="..." fill="#06CB60"/>

水塔svg代码。

<svg width="120" height="120" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24 67C24 64.7909 25.7909 63 28 63V111H24V67Z" fill="url(#paint0_linear_123_2793)"/>
<path d="M30 111H22V112H25V113H24V116H25V117H22V118H30V117H27V116H28V113H27V112H30V111Z" fill="url(#paint1_linear_123_2793)"/>
<path d="M76 94L80 90V111H76V94Z" fill="url(#paint2_linear_123_2793)"/>
<path d="M82 111H74V112H77V113H76V116H77V117H74V118H82V117H79V116H80V113H79V112H82V111Z" fill="url(#paint3_linear_123_2793)"/>
<path d="M40 90L44 94V111H40V90Z" fill="url(#paint4_linear_123_2793)"/>
<path d="M46 111H38V112H41V113H40V116H41V117H38V118H46V117H43V116H44V113H43V112H46V111Z" fill="url(#paint5_linear_123_2793)"/>
<path d="M92 63C94.2091 63 96 64.7909 96 67V111H92V63Z" fill="url(#paint6_linear_123_2793)"/>
<path d="M98 111H90V112H93V113H92V116H93V117H90V118H98V117H95V116H96V113H95V112H98V111Z" fill="url(#paint7_linear_123_2793)"/>
<g filter="url(#filter0_i_123_2793)">
<path d="M28 17.4163C28 15.4606 28 14.4828 28.3154 13.6374C28.5941 12.8904 29.0474 12.2209 29.6375 11.6847C30.3053 11.0779 31.2131 10.7147 33.0289 9.98845L53 2H67L86.9711 9.98845C88.7869 10.7147 89.6947 11.0779 90.3625 11.6847C90.9526 12.2209 91.4059 12.8904 91.6846 13.6374C92 14.4828 92 15.4606 92 17.4163V78L71.3137 98.6863C67.3535 102.646 65.3735 104.627 63.0902 105.368C61.0817 106.021 58.9183 106.021 56.9098 105.368C54.6265 104.627 52.6465 102.646 48.6863 98.6863L28 78V17.4163Z" fill="#ECECEC"/>
</g>
<path d="M91.5 17.4163V77.7929L70.9601 98.3327C68.9742 100.319 67.5058 101.787 66.2495 102.853C64.9977 103.916 63.9895 104.55 62.9357 104.893C61.0276 105.513 58.9724 105.513 57.0643 104.893C56.0105 104.55 55.0023 103.916 53.7505 102.853C52.4942 101.787 51.0258 100.319 49.0398 98.3327L28.5 77.7929V17.4163C28.5 15.4207 28.5076 14.5527 28.7839 13.8122C29.0347 13.1399 29.4426 12.5373 29.9737 12.0548C30.5587 11.5232 31.3618 11.1938 33.2146 10.4527L53.0963 2.5H66.9037L86.7854 10.4527C88.6382 11.1938 89.4413 11.5232 90.0263 12.0548C90.5574 12.5373 90.9653 13.1399 91.2161 13.8122C91.4924 14.5527 91.5 15.4207 91.5 17.4163Z" stroke="#C7C7C7"/>
<mask id="mask0_123_2793" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="28" y="2" width="64" height="104">
<rect width="64" height="104" transform="matrix(1 0 0 -1 28 106)" fill="white"/>
</mask>
<g mask="url(#mask0_123_2793)">
<g filter="url(#filter1_i_123_2793)">
<path d="M28 17.4163C28 15.4606 28 14.4828 28.3154 13.6374C28.5941 12.8904 29.0474 12.2209 29.6375 11.6847C30.3053 11.0779 31.2131 10.7147 33.0289 9.98845L53 2H67L86.9711 9.98845C88.7869 10.7147 89.6947 11.0779 90.3625 11.6847C90.9526 12.2209 91.4059 12.8904 91.6846 13.6374C92 14.4828 92 15.4606 92 17.4163V78L71.3137 98.6863C67.3535 102.646 65.3735 104.627 63.0902 105.368C61.0817 106.021 58.9183 106.021 56.9098 105.368C54.6265 104.627 52.6465 102.646 48.6863 98.6863L28 78V17.4163Z" fill="#06CB60"/>
</g>
<path d="M91.5 17.4163V77.7929L70.9601 98.3327C68.9742 100.319 67.5058 101.787 66.2495 102.853C64.9977 103.916 63.9895 104.55 62.9357 104.893C61.0276 105.513 58.9724 105.513 57.0643 104.893C56.0105 104.55 55.0023 103.916 53.7505 102.853C52.4942 101.787 51.0258 100.319 49.0398 98.3327L28.5 77.7929V17.4163C28.5 15.4207 28.5076 14.5527 28.7839 13.8122C29.0347 13.1399 29.4426 12.5373 29.9737 12.0548C30.5587 11.5232 31.3618 11.1938 33.2146 10.4527L53.0963 2.5H66.9037L86.7854 10.4527C88.6382 11.1938 89.4413 11.5232 90.0263 12.0548C90.5574 12.5373 90.9653 13.1399 91.2161 13.8122C91.4924 14.5527 91.5 15.4207 91.5 17.4163Z" stroke="#C7C7C7"/>
</g>
<defs>
<filter id="filter0_i_123_2793" x="28" y="2" width="64" height="103.858" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="8"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.33 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_123_2793"/>
</filter>
<filter id="filter1_i_123_2793" x="28" y="2" width="64" height="103.858" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="8"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.33 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_123_2793"/>
</filter>
<linearGradient id="paint0_linear_123_2793" x1="28" y1="89.9189" x2="24" y2="89.9189" gradientUnits="userSpaceOnUse">
<stop stop-color="#C7C7C7"/>
<stop offset="0.515625" stop-color="#ECECEC"/>
<stop offset="1" stop-color="#C7C7C7"/>
</linearGradient>
<linearGradient id="paint1_linear_123_2793" x1="21" y1="114.5" x2="31" y2="114.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#A7A7A7"/>
<stop offset="0.510417" stop-color="#D7D7D7"/>
<stop offset="1" stop-color="#A7A7A7"/>
</linearGradient>
<linearGradient id="paint2_linear_123_2793" x1="80" y1="98.0473" x2="76" y2="98.0473" gradientUnits="userSpaceOnUse">
<stop stop-color="#C7C7C7"/>
<stop offset="0.515625" stop-color="#ECECEC"/>
<stop offset="1" stop-color="#C7C7C7"/>
</linearGradient>
<linearGradient id="paint3_linear_123_2793" x1="73" y1="114.5" x2="83" y2="114.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#A7A7A7"/>
<stop offset="0.510417" stop-color="#D7D7D7"/>
<stop offset="1" stop-color="#A7A7A7"/>
</linearGradient>
<linearGradient id="paint4_linear_123_2793" x1="44" y1="98.0471" x2="40" y2="98.0471" gradientUnits="userSpaceOnUse">
<stop stop-color="#C7C7C7"/>
<stop offset="0.515625" stop-color="#ECECEC"/>
<stop offset="1" stop-color="#C7C7C7"/>
</linearGradient>
<linearGradient id="paint5_linear_123_2793" x1="37" y1="114.5" x2="47" y2="114.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#A7A7A7"/>
<stop offset="0.510417" stop-color="#D7D7D7"/>
<stop offset="1" stop-color="#A7A7A7"/>
</linearGradient>
<linearGradient id="paint6_linear_123_2793" x1="96" y1="89.9189" x2="92" y2="89.9189" gradientUnits="userSpaceOnUse">
<stop stop-color="#C7C7C7"/>
<stop offset="0.515625" stop-color="#ECECEC"/>
<stop offset="1" stop-color="#C7C7C7"/>
</linearGradient>
<linearGradient id="paint7_linear_123_2793" x1="89" y1="114.5" x2="99" y2="114.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#A7A7A7"/>
<stop offset="0.510417" stop-color="#D7D7D7"/>
<stop offset="1" stop-color="#A7A7A7"/>
</linearGradient>
</defs>
</svg>

既然已经用 svg 了,那么就直接用 svg 来画一个整体的水塔,中间部分用 js 控制高度变化作为进度条就好了。

或者简单一点,同遮罩的形式,或者把中间那部分镂空,用一个 png 图,盖在一个矩形的渐变图上面,这样就可以直接通过控制矩形的高度就好了。

简单的类似的 demo,可以参考这个:http://lab.tianyizone.com/demo/ecg/

你把它想象成两个div,第一个容器的div是不规则的棱形并且添加了overflow:hidden;将绿色的div隐藏,此时只需要调整绿色div的高度即可
image.png

给你用svg 画了一个 用js手动控制一下颜色和进度就行 demo

推荐问题
宣传栏