旋转式多点SVG线性梯度混合 [英] Rotatable Multi-stop SVG linear gradient mixin

查看:137
本文介绍了旋转式多点SVG线性梯度混合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个多点SVG线性梯度混合器,但是在旋转以模仿css3线性梯度规格时,我很难使SVG缩放.它完美适用于水平和垂直渐变.在45、135、225和315度时,它也可以完美工作,但前提是对象的比例为1:1.否则,那是不对的!

I have created a multi-stop SVG linear gradient mixin but I am having trouble getting the SVG to scale when rotating to mimic the css3 linears-gradient spec. It works perfectly for horizontal and vertical gradients. At 45, 135, 225 and 315 degrees it also works perfectly but only if the ratio of the object is 1:1. Otherwise, it's just not quite right!

我尝试过使用prepareAspectRatio ="xMaxYMax Meet"等,并尝试使事情的背景大小:cover或contain,但没有任何一件作品能令人满意.

I tried playing with preserveAspectRatio="xMaxYMax meet" etc. and tried to get things working with background-size:cover or contain, but nothing would work satisfactory.

我最初在LESS中尝试了svg-gradient()函数,但没有完成我需要做的事情(请参阅我以前的文章-

I originally tried the svg-gradient() function in LESS but it didn't do what I needed it to do (see my previous post - less-svg-gradient-function-with-multiple-variables) - so that is what led me down this path.

任何人都有一个符合css3规范的公式吗?

Does anyone have a formula that is precise to the css3 spec ??

这是我到目前为止所拥有的,...我还没有在网上找到类似的东西.

Here is what I have so far,... I haven't found anything quite like this on the net.

.multigradient(@id: gradient;@size: contain; @direction: to right; @color){
  .case(@direction); // apply named direction values
  .case(@a) when (@a = ~"to top"){@part2:~'x1="0%" y1="100%" x2="0%" y2="0%">';@angle:@direction;@angle2: ~"bottom";}
  .case(@a) when (@a = ~"to top right"){@part2:~'x1="0%" y1="100%" x2="100%" y2="0%">';@angle:@direction;@angle2: ~"bottom left";}
  .case(@a) when (@a = ~"to right"){@part2:~'x1="0%" y1="0%" x2="100%" y2="0%">';@angle:@direction;@angle2: ~"left";}
  .case(@a) when (@a = ~"to bottom right"){@part2:~'x1="0%" y1="0%" x2="100%" y2="100%">';@angle:@direction;@angle2: ~"top left";}
  .case(@a) when (@a = ~"to bottom"){@part2:~'x1="0%" y1="0%" x2="0%" y2="100%">';@angle:@direction;@angle2: ~"top";}
  .case(@a) when (@a = ~"to bottom left"){@part2:~'x1="100%" y1="0%" x2="0%" y2="100%">';@angle:@direction;@angle2: ~"top right";}
  .case(@a) when (@a = ~"to left"){@part2:~'x1="100%" y1="0%" x2="0%" y2="0%">';@angle:@direction;@angle2: ~"right";}
  .case(@a) when (@a = ~"to top left"){@part2:~'x1="100%" y1="100%" x2="0%" y2="0%">';@angle:@direction;@angle2: ~"bottom right";}
  .case(@a) when (isnumber(@a) = true) {  // for numerical values
    @angle: unit(@a, deg);  //send degrees unchanged to standards-compliant linear-gradient
    @angle2: 90 - @angle;  //send degrees corrected to old -prefixed-linear-gradients
    .calc(@a + 90); // calculate svg co-ords
    .calc(@b) when (@b < 0){ @c: @b + 360; .calc(@c); }
    .calc(@b) when (@b >= 360){ @c: mod(@b, 360); .calc(@c); }
    .calc(@b) when (@b >= 0) and (@b < 45) {@x1: 100;@y1: 50 + (tan(unit(@b, deg)) * 50);@x2: 0;@y2: 50 - (tan(unit(@b, deg)) * 50);}
    .calc(@b) when (@b >= 45) and (@b < 90){@x1: 100 - (tan(unit(mod(@b, 45), deg)) * 50);@y1: 100;@x2: tan(unit(mod(@b, 45), deg)) * 50;@y2: 0;}
    .calc(@b) when (@b >= 90) and (@b < 135){@x1: 50 - (tan(unit(mod(@b, 45), deg)) * 50);@y1: 100;@x2: 50 + (tan(unit(mod(@b, 45), deg)) * 50);@y2: 0;}
    .calc(@b) when (@b >= 135) and (@b < 180){@x1: 0;@y1: 100 - (tan(unit(mod(@b, 45), deg)) * 50);@x2: 100;@y2: tan(unit(mod(@b, 45), deg)) * 50;}
    .calc(@b) when (@b >= 180) and (@b < 225){@x1: 0;@y1: 50 - (tan(unit(mod(@b, 45), deg)) * 50);@x2: 100;@y2: 50 + (tan(unit(mod(@b, 45), deg)) * 50);}
    .calc(@b) when (@b >= 225) and (@b < 270){@x1: tan(unit(mod(@b, 45), deg)) * 50;@y1: 0;@x2: 100 - (tan(unit(mod(@b, 45), deg)) * 50);@y2: 100;}
    .calc(@b) when (@b >= 270) and (@b < 315){@x1: 50 + (tan(unit(mod(@b, 45), deg)) * 50);@y1: 0;@x2: 50 - (tan(unit(mod(@b, 45), deg)) * 50);@y2: 100;}
    .calc(@b) when (@b >= 315) and (@b < 360){@x1: 100;@y1: tan(unit(mod(@b, 45), deg)) * 50;@x2: 0;@y2: 100 - (tan(unit(mod(@b, 45), deg)) * 50);}
    /*output: ~"svg co-ords:- x1: @{x1} y1: @{y1} x2: @{x2} y2: @{y2}";*/  // enable to print values to stylesheet (for debugging)
    @part2:~'x1="@{x1}%" y1="@{y1}%" x2="@{x2}%" y2="@{y2}%">';
  }
  .loop(length(@color), ~"");  //loop through colours and append to the variable 
  .loop(@i,@d) when (@i > 0) {
    @stop: extract(@color, @i);
    @offset: extract(@stop, 2) ;
    @stopcolor: extract(@stop, 1) ;
    @part3:~'<stop offset="@{offset}" stop-color="@{stopcolor}" />@{d}';
    .case2(@i);
    .case2(@z) when (@z = 1){  // on final loop construct and encode svg
      @part1:~'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none"><linearGradient id="@{id}" gradientUnits="userSpaceOnUse" ';
      @part4:~'</linearGradient><rect x="0" y="0" width="1" height="1" fill="url(#@{id})" /></svg>';
      /*output2: ~"@{part1}@{part2}@{part3}@{part4}";*/  // enable to print unencoded svg to stylesheet (for debugging)
      // Thank you to Phil Brown for B64encode, taken from - http://blog.philipbrown.id.au/2012/09/base64-encoded-svg-gradient-backgrounds-in-less/
      @dataPrefix: ~"url(data:image/svg+xml;base64,";
      @dataSuffix: ~")";
      @dataContent: ~"@{part1}@{part2}@{part3}@{part4}";
      @b64Out: ~`(function(a,b,c){function e(a){a=a.replace(/\r\n/g,'\n');var b='';for(var c=0;c<a.length;c++){var d=a.charCodeAt(c);if(d<128){b+=String.fromCharCode(d)}else if(d>127&&d<2048){b+=String.fromCharCode(d>>6|192);b+=String.fromCharCode(d&63|128)}else{b+=String.fromCharCode(d>>12|224);b+=String.fromCharCode(d>>6&63|128);b+=String.fromCharCode(d&63|128)}}return b}function f(a){var b='';var c,f,g,h,i,j,l;var m=0;a=e(a);while(m<a.length){c=a.charCodeAt(m++);f=a.charCodeAt(m++);g=a.charCodeAt(m++);h=c>>2;i=(c&3)<<4|f>>4;j=(f&15)<<2|g>>6;l=g&63;if(isNaN(f)){j=l=64}else if(isNaN(g)){l=64}b=b+d.charAt(h)+d.charAt(i)+d.charAt(j)+d.charAt(l)}return b}var d='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';return a+f(b)+c})('@{dataPrefix}','@{dataContent}','@{dataSuffix}')`;
      background: ~"@{b64Out}";  // print the mofo to the css
    }
    .loop((@i - 1),@part3);    // next iteration sends variable to be joined
  } 
  background: -moz-linear-gradient(@angle2, @color);
  background: -webkit-linear-gradient(@angle2, @color);
  background: -ms-linear-gradient(@angle2, @color);
  background: -o-linear-gradient(@angle2, @color);
  background: linear-gradient(@angle, @color);
  background-size: @size;
}

// Test cases: requires id, size, angle, at least two colorstops
// =============================================================
.my-class{
  .multigradient(gradient2; contain; 0; red 0, orange 16.6%, yellow 33.3%, green 50%, blue 66.6%, indigo 83.3%, violet 100%);
}
.my-class2{
  .multigradient(i-am-unique; contain; to top right; red 0, green 50%, blue 100%);
}
.my-class3{
  .multigradient(grad3; cover; 135; pink 0, rgba(0,0,255,1.0) 50%, #fff 100%);
}
.my-class4{
  .multigradient(grad4; contain; to top; pink 0, blue 50%, white 100%);
}
.my-class5{
  .multigradient(grad5; cover; to bottom; rgba(0,2,174,1) 0%, rgba(0,2,174,1) 22.32142857142857%, rgba(0,2,137,1) 22.32142857142857%, rgba(0,2,137,1) 32.14285714285714%, rgba(0,1,48,1) 32.14285714285714%, rgba(1,32,99,1) 60.71428571428571%, rgba(3,41,112,1) 60.71428571428571%, rgba(3,41,112,1) 64.28571428571429%, rgba(0,9,45,1) 64.28571428571429%, rgba(0,9,45,1) 96.42857142857143%, rgba(3,41,112,1) 96.42857142857143%, rgba(3,41,112,1) 100%);
}
.my-class6{
  .multigradient(browns; cover; 45; DarkKhaki 0, Khaki 4%, PaleGoldenrod 8%, PeachPuff 12%, Moccasin 16%, PapayaWhip 20%, LightGoldenrodYellow 24%, LemonChiffon 28%, LightYellow 32%, Cornsilk 36%, BlanchedAlmond 40%, Bisque 44%, NavajoWhite 48%, Wheat 52%, BurlyWood 56%, Tan 60%, RosyBrown 64%, SandyBrown 68%, Goldenrod 72%, DarkGoldenrod 76%, Peru 80%, Chocolate 84%, SaddleBrown 88%, Sienna 92%, Brown 96%, Maroon 100%);
}
//  HTML for test cases
//  ===================
<div style="border:1px solid #000;height:200px;width:200px;display:inline-block;" class="my-class"></div>
<div style="border:1px solid #000;height:200px;width:200px;display:inline-block;" class="my-class2"></div>
<div style="border:1px solid #000;height:200px;width:200px;display:inline-block;" class="my-class3"></div>
<div style="border:1px solid #000;height:200px;width:200px;display:inline-block;" class="my-class4"></div>
<div style="border:1px solid #000;height:200px;width:200px;display:inline-block;" class="my-class5"></div>
<div style="border:1px solid #000;height:200px;width:400px;display:inline-block;" class="my-class6"></div>

只需剪切并粘贴到类似 codepen

Just cut and paste into something like codepen

推荐答案

最后,我已经解决了我的问题!我创建了一个具有长宽比的LESS可旋转的多点线性渐变SVG mixin,以保持旋转真实.在我看来,比Colorzilla或MS渐变器生成的SVG更强大,因为它设置了x1 y1 x2和y2值以及viewBox,因此您可以精确地旋转渐变而不会变形. :)

Finally I have a solution to my problem! I have created a LESS rotatable multi-stop linear gradient SVG mixin with aspect ratio to keep rotation true. More powerful in my honest opinion than the SVGs generated by Colorzilla or the MS gradient maker as it sets the x1 y1 x2 and y2 values as well as viewBox so you can rotate the gradient precisely without distortion. :)

生成SVG渐变所需要做的就是这个,... (ID,角度,色标,比率)

All you need to do to generate a SVG gradient is as little as this,... (ID, angle, colorstops, ratio)

.multigradient(uniqueID; 45; #fff 0, #000 100%; 2, 1);

在Codepen上可旋转的多级SVG线性渐变混合

这篇关于旋转式多点SVG线性梯度混合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆