游过对岸 發表於 2019-11-26 10:22:00

react实战 : react 与 svg

<p>有一个需求是这样的。</p>
<p>一个组件里若干个区块。区块数量不定。</p>
<p>区块里面是一个波浪效果组件,而这个一般用 SVG 做。</p>
<p>所以就变成了在 react 中使用 SVG 的问题。</p>
<p>&nbsp;</p>
<p>首先是波浪效果需要的样式。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">.p{
font</span>-<span style="color: rgba(0, 0, 0, 1)">size: 12px;
line</span>-height: 2<span style="color: rgba(0, 0, 0, 1)">;
text</span>-<span style="color: rgba(0, 0, 0, 1)">align: center;
margin:</span>0<span style="color: rgba(0, 0, 0, 1)">;
width: 52px;
color: #fff;
}

.irrigate_svg {
height: 52px;
width: 52px;
}
.masked {
</span>-webkit-<span style="color: rgba(0, 0, 0, 1)">mask: url(#myMask);
mask: url(#myMask);
}
.irrigate_wrap {
transform: translateY(112px);
}
.irrigate_svg {
overflow: hidden;
}
.irrigate_rate {
animation</span>-<span style="color: rgba(0, 0, 0, 1)">name:wavingleft, wavingUp;
animation</span>-<span style="color: rgba(0, 0, 0, 1)">duration:6s, 6s;
animation</span>-timing-<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">:linear, linear;
animation</span>-iteration-count:infinite, 1<span style="color: rgba(0, 0, 0, 1)">;
}
@keyframes wavingleft {
</span>0%<span style="color: rgba(0, 0, 0, 1)"> {
    transform: translateX(</span>-<span style="color: rgba(0, 0, 0, 1)">239px);
}
</span>50%<span style="color: rgba(0, 0, 0, 1)"> {
    transform: translateX(0px);
}
</span>100%<span style="color: rgba(0, 0, 0, 1)"> {
    transform: translateX(</span>-<span style="color: rgba(0, 0, 0, 1)">239px);
}
}
@keyframes wavingright {
</span>0%<span style="color: rgba(0, 0, 0, 1)"> {
    transform: translateX(0px);
}
</span>50%<span style="color: rgba(0, 0, 0, 1)"> {
    transform: translateX(</span>-<span style="color: rgba(0, 0, 0, 1)">239px);
}
</span>100%<span style="color: rgba(0, 0, 0, 1)"> {
    transform: translateX(0px);
}
}
@keyframes wavingUp{
</span>0%<span style="color: rgba(0, 0, 0, 1)"> {
    transform: translateX(</span>-<span style="color: rgba(0, 0, 0, 1)">239px) translateY(100px);
}
</span>50%<span style="color: rgba(0, 0, 0, 1)"> {
    transform: translateX(0px);
}
</span>100%<span style="color: rgba(0, 0, 0, 1)"> {
    transform: translateX(</span>-<span style="color: rgba(0, 0, 0, 1)">239px) translateY(0px);
}
}</span></pre>
</div>
<p>&nbsp;</p>
<p>引入样式,以及组件文件的结构。</p>
<div class="cnblogs_code">
<pre>import React from 'react'<span style="color: rgba(0, 0, 0, 1)">
import Styles from </span>'./waveContainer.less'<span style="color: rgba(0, 0, 0, 1)">

class Wave extends React.Component {}

class WaveContainer extends React.Component {}

export </span><span style="color: rgba(0, 0, 255, 1)">default</span> WaveContainer</pre>
</div>
<p>一个组件文件里可能有很多层组件,只需要输出最外面的一层。</p>
<p>&nbsp;</p>
<p>SVG 组件。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">class Wave extends React.Component {
constructor(props){
    super(props)
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.state =<span style="color: rgba(0, 0, 0, 1)"> {
    }
}

render(){
    const item </span>= <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.props.data

    const getNumberPosition </span>= (number) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      let style
      const s </span>=<span style="color: rgba(0, 0, 0, 1)"> {
      s1:</span>"matrix(1 0 0 1 96.44 150)"<span style="color: rgba(0, 0, 0, 1)">,
      s2:</span>"matrix(1 0 0 1 66.44 150)"<span style="color: rgba(0, 0, 0, 1)">,
      s3:</span>"matrix(1 0 0 1 46.44 150)"<span style="color: rgba(0, 0, 0, 1)">,
      }

      </span><span style="color: rgba(0, 0, 255, 1)">switch</span><span style="color: rgba(0, 0, 0, 1)"> (parseInt(number).toString().length) {
      </span><span style="color: rgba(0, 0, 255, 1)">case</span> 0<span style="color: rgba(0, 0, 0, 1)">:
          style </span>=<span style="color: rgba(0, 0, 0, 1)"> s.s2
          </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">case</span> 1<span style="color: rgba(0, 0, 0, 1)">:
          style </span>=<span style="color: rgba(0, 0, 0, 1)"> s.s1
          </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">case</span> 2<span style="color: rgba(0, 0, 0, 1)">:
          style </span>=<span style="color: rgba(0, 0, 0, 1)"> s.s2
          </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">case</span> 3<span style="color: rgba(0, 0, 0, 1)">:
          style </span>=<span style="color: rgba(0, 0, 0, 1)"> s.s3
          </span><span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
      </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)">:
          style </span>=<span style="color: rgba(0, 0, 0, 1)"> s.s2
      }
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> style
    }

    const getColor </span>= (item) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> item.color
    }

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;div &gt;
      &lt;div className={Styles.irrigate_svg}&gt;
          &lt;svg version="1.1" id="图层_5" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 244.2 244.2" style={{ enableBackground:"new 0 0 244.2 244.2" }} &gt;
            &lt;defs&gt;
            &lt;mask id="myMask"&gt;
                &lt;circle style={{ fill:"#fff",stroke:"#fff","strokeMiterlimit":"10" }} cx="122.1" cy="122.1" r="122.1"/&gt;
            &lt;/mask&gt;
            &lt;/defs&gt;
            &lt;g className={Styles.masked}&gt;
            &lt;g className={Styles.irrigate_wrap}&gt;<span style="color: rgba(0, 0, 0, 1)">
                {</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> &lt;linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="1120.8899" y1="262.1278" x2="1120.8899" y2="1.81" gradientTransform="matrix(-1 0 0 -1 1430.8899 246)"&gt;
                  &lt;stopoffset="0" style={{ stopColor:getColor(item),"stopOpacity":"0.8" }}/&gt;
                  &lt;stopoffset="1" style={{ stopColor:getColor(item),"stopOpacity":"0.7"}}/&gt;
                &lt;/linearGradient&gt; </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">}
                </span>&lt;path className={Styles.irrigate_rate} style={{ fill:getColor(item) }} d="<span style="color: rgba(0, 0, 0, 1)">M0-3.8c0,0,44.7-14.3,77-12.1c32.9,2.3,95.6,33.3,128.3,31.1c38.9-2.6,116.7-33.7,153-29.7
                  c22.9,2.5,73,20.4,95.7,24.4c30.9,5.5,64.2,8.4,90.3,6.8C567.8,15.2,620-3.8,620-3.8v248H0V-3.8z</span>"/&gt;
            &lt;/g&gt;
            &lt;/g&gt;
            &lt;g&gt;
            &lt;g id="图层_5-2"&gt;
                &lt;circle style={{ fill:"none",stroke:"#25437C",strokeWidth:"1",strokeMiterlimit:"1" }} cx="122.1" cy="122.1" r="122.1"/&gt;
                &lt;text transform={getNumberPosition(item.data)} style={{ fill:"#FFF", fontSize:"100px" }}&gt; {item.data} &lt;/text&gt;
                  &lt;linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="0" y1="123.91" x2="244.18" y2="123.91" gradientTransform="matrix(1 0 0 -1 0 246)"&gt;
                  &lt;stopoffset="0" style={{ stopColor:"rgb(55,107,112)" }}/&gt;
                  &lt;stopoffset="1" style={{ stopColor:"rgb(55,107,112)" }}/&gt;
                  &lt;/linearGradient&gt;
                &lt;circle style={{ fill:"none",stroke:"url(#SVGID_3_)",strokeWidth:"1",strokeLinecap:"round",strokeMiterlimit:"1" }} cx="122.1" cy="122.1" r="122.1"/&gt;
            &lt;/g&gt;
            &lt;/g&gt;
          &lt;/svg&gt;
      &lt;/div&gt;
      &lt;p className={Styles.p}&gt; {item.name} &lt;/p&gt;
      &lt;/div&gt;
<span style="color: rgba(0, 0, 0, 1)">    );
}
}</span></pre>
</div>
<p>&nbsp;</p>
<p>SVG原本怎么写,JSX就怎么写。</p>
<p>但是遇到了一个问题。</p>
<div><span style="color: rgba(255, 0, 0, 1)">linearGradient</span>, 这个用来做渐变的标签,直接使用没有问题,但如果循环输出的时候把需要的值赋值进去,就会发现所有 SVG 组件的颜色都和第一个一样了。而用开发者工具查看的时候,颜色确实是赋值进去了。不知道是怎么回事。</div>
<div>&nbsp;</div>
<div>然后是容器组件。</div>
<div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">class WaveContainer extends React.Component {
constructor(props){
    super(props)
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.state =<span style="color: rgba(0, 0, 0, 1)"> {
    }
}

render(){
    const baseFlex </span>=<span style="color: rgba(0, 0, 0, 1)"> {
      display: </span>'flex'<span style="color: rgba(0, 0, 0, 1)">,
      justifyContent: </span>'center'<span style="color: rgba(0, 0, 0, 1)">,
      alignItems: </span>'center'<span style="color: rgba(0, 0, 0, 1)">
    }
    const theStyle </span>=<span style="color: rgba(0, 0, 0, 1)"> {
      main:{
      ...baseFlex,
      width:</span>'100%'<span style="color: rgba(0, 0, 0, 1)">,
      height:</span>'100%'<span style="color: rgba(0, 0, 0, 1)">,
      color:</span>"#fff"<span style="color: rgba(0, 0, 0, 1)">
      },
      tem:{
      ...baseFlex,
      flex:</span>"auto"<span style="color: rgba(0, 0, 0, 1)">,
      color:</span>'#fff'<span style="color: rgba(0, 0, 0, 1)">
      },
      shellA:{
      ...baseFlex,
      width:</span>'100%'<span style="color: rgba(0, 0, 0, 1)">,
      height:</span>'100%'<span style="color: rgba(0, 0, 0, 1)">
      },
      shellB:{
      ...baseFlex,
      width:</span>'100%'<span style="color: rgba(0, 0, 0, 1)">,
      height:</span>'50%'<span style="color: rgba(0, 0, 0, 1)">
      }
    }

    </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> const dataBar = this.props.dataBar</span>
<span style="color: rgba(0, 0, 0, 1)">
    const dataBar </span>= (() =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">this</span>.props.curcity &amp;&amp; <span style="color: rgba(0, 0, 255, 1)">this</span>.props.curcity === 'all'<span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
          data:{
            sData:[
            { name: </span>'a', data: 55, color:'rgb(79,239,223)'<span style="color: rgba(0, 0, 0, 1)"> },
            { name: </span>'a', data: 5, color:'rgb(79,239,223)'<span style="color: rgba(0, 0, 0, 1)">},
            { name: </span>'a', data: 36, color:'rgb(79,239,223)'<span style="color: rgba(0, 0, 0, 1)">},
            { name: </span>'a', data: 476, color:'rgb(87,207,30)'<span style="color: rgba(0, 0, 0, 1)">},
            { name: </span>'a', data: 226, color:'rgb(79,239,223)'<span style="color: rgba(0, 0, 0, 1)">},
            { name: </span>'a', data: 273, color:'rgb(251,211,36)'<span style="color: rgba(0, 0, 0, 1)">}
            ]
          }
      }
      } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> {
          data:{
            sData:[
            { name: </span>'a', data: 124, color:'rgb(79,239,223)'<span style="color: rgba(0, 0, 0, 1)"> },
            { name: </span>'a', data: 253, color:'rgb(79,239,223)'<span style="color: rgba(0, 0, 0, 1)">},
            { name: </span>'a', data: 321, color:'rgb(79,239,223)'<span style="color: rgba(0, 0, 0, 1)">},
            { name: </span>'a', data: 156, color:'rgb(87,207,30)'<span style="color: rgba(0, 0, 0, 1)">},
            { name: </span>'a', data: 2, color:'rgb(79,239,223)'<span style="color: rgba(0, 0, 0, 1)">},
            { name: </span>'a', data: 77, color:'rgb(251,211,36)'<span style="color: rgba(0, 0, 0, 1)">}
            ]
          }
      }
      }
    })()

    const Container </span>= ((dataBar) =&gt;<span style="color: rgba(0, 0, 0, 1)"> {

      const flexMatrix </span>=<span style="color: rgba(0, 0, 0, 1)"> [
      [</span>0,0<span style="color: rgba(0, 0, 0, 1)">],
      [</span>1,0<span style="color: rgba(0, 0, 0, 1)">],
      [</span>2,0<span style="color: rgba(0, 0, 0, 1)">],
      [</span>3,0<span style="color: rgba(0, 0, 0, 1)">],
      [</span>2,2<span style="color: rgba(0, 0, 0, 1)">],
      [</span>3,2<span style="color: rgba(0, 0, 0, 1)">],
      [</span>3,3<span style="color: rgba(0, 0, 0, 1)">],
      [</span>4,3<span style="color: rgba(0, 0, 0, 1)">],
      [</span>4,4<span style="color: rgba(0, 0, 0, 1)">],
      [</span>5,4<span style="color: rgba(0, 0, 0, 1)">],
      [</span>5,5<span style="color: rgba(0, 0, 0, 1)">],
      [</span>6,5<span style="color: rgba(0, 0, 0, 1)">],
      [</span>6,6<span style="color: rgba(0, 0, 0, 1)">]
      ]

      const sData </span>=<span style="color: rgba(0, 0, 0, 1)"> dataBar.data.sData
      const length </span>=<span style="color: rgba(0, 0, 0, 1)"> sData.length

      const matrix </span>= flexMatrix ? flexMatrix : flexMatrix

      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (matrix === 0<span style="color: rgba(0, 0, 0, 1)">) {
      </span><span style="color: rgba(0, 0, 255, 1)">return</span> ""<span style="color: rgba(0, 0, 0, 1)">
      }

      let temShell, temA, temB

      temA </span>= sData.slice(0, matrix).map((item, index) =&gt;
      &lt;div style={theStyle.tem} key={index.toString()}&gt; &lt;Wave data={item} /&gt; &lt;/div&gt;<span style="color: rgba(0, 0, 0, 1)">
      );

      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (matrix === 0<span style="color: rgba(0, 0, 0, 1)">) {
      temB </span>= ""<span style="color: rgba(0, 0, 0, 1)">
      } </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
      temB </span>= sData.slice(matrix, (matrix + matrix)).map((item, index) =&gt;
          &lt;div style={theStyle.tem} key={index.toString()}&gt; &lt;Wave data={item} /&gt; &lt;/div&gt;<span style="color: rgba(0, 0, 0, 1)">
      );
      }

      </span><span style="color: rgba(0, 0, 255, 1)">if</span> (matrix === 0<span style="color: rgba(0, 0, 0, 1)">) {
      temShell </span>= &lt;div style={theStyle.shellA} &gt; {temA} &lt;/div&gt;
      } <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
      temShell </span>= .map((item, index) =&gt;
          &lt;div style={theStyle.shellB} key={"temShell" + index.toString()}&gt; {index === 0 ? temA : temB} &lt;/div&gt;
<span style="color: rgba(0, 0, 0, 1)">      );

      theStyle.main.flexWrap </span>= "wrap"<span style="color: rgba(0, 0, 0, 1)">
      }

      console.log(temShell)
      
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> temShell
    })(dataBar)

    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;div style={theStyle.main}&gt;<span style="color: rgba(0, 0, 0, 1)">
      {</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> &lt;Wave /&gt; </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">}
      { Container }
      </span>&lt;/div&gt;
<span style="color: rgba(0, 0, 0, 1)">    );
}
}</span></pre>
</div>
<p>&nbsp;</p>
<p>以上。</p>
</div><br><br>
来源:https://www.cnblogs.com/foxcharon/p/11933649.html
頁: [1]
查看完整版本: react实战 : react 与 svg