【问题标题】:HTML css linear-gradient not working as expectedHTML css 线性渐变未按预期工作
【发布时间】:2020-01-01 11:12:35
【问题描述】:

我只是在 css 中使用线性渐变,顺便说一句,生成的渐变效果与设计不同。我从来没有在任何 Android、iOS、React Native 或 HTML5 画布上遇到过这个问题,但只是在 css 上。

.gradient {
  background-image: linear-gradient(to right top, red, blue);
}

为了展示 css 的 linear-gradient 和 canvas 的 create createLinearGradient 之间的差异,我做了一个小提琴。 请检查此fiddle link

上面是css渐变,下面是canvas之一。 如您所见,画布的createLinearGradient 工作正常,但在css 上same-color-line(上图中的黄线)不垂直于渐变的方向,而是看起来像元素的另一个diagonal。 有什么理由为什么它在 css 中?

【问题讨论】:

  • 这很好地解释了事情:developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient。它显示为这样,因为您添加了“顶部”值
  • @Sorix,非常感谢,您的链接对于理解线性渐变非常有帮助,顺便说一句,我必须将渐变设置为任何动态矩形元素的右上角。我的情况在 css 中有什么解决方案吗?
  • 可能使用角度而不是顶部或底部。如果我理解正确,你的渐变应该总是在同一个角度......像这样:linear-gradient(45deg, red, blue);
  • 用交互式演示更新了我的答案

标签: html css html5-canvas linear-gradients


【解决方案1】:

这是设计使然。您可以在此处阅读更多信息:https://drafts.csswg.org/css-images-3/#linear-gradients

如果参数指定了盒子的一个角,例如to top left渐变线必须倾斜,使其指向与指定角相同的象限,并且垂直于与渐变框的两个相邻角相交的线。这会导致 50% 处的色标与相邻的两个角相交。

基本上,当使用这样的关键字时,你会得到一种从角落开始的拉伸梯度,你会失去对角线的垂直特征。

.child {
  position:relative;
  width: 100px;
  height: 100px;
  border: 1px solid red;
  background-image: linear-gradient(to top right, red 50%, blue 0);
}
.child.alt {
  width:200px;
}

.child:before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  background:linear-gradient(to top left,transparent calc(50% - 5px),green,transparent calc(50% + 5px) );
}
this one is good because it's a square
<div class="child"></div>
but not this one
<div class="child alt"></div>

如果您想获得第二个输出,您需要使用显式角度并找到使渐变线与对角线相同的角度,为此您需要考虑等于arctang(width/height)的角度

在您的情况下,它将是 arctang(300/75) = arctang(4) = 75.69deg。由于您使用的是 JS,因此您可以轻松进行此计算。

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

var grd = ctx.createLinearGradient(0, 75, 300, 0);
grd.addColorStop(0, "red");
grd.addColorStop(1, "blue");

ctx.fillStyle = grd;
ctx.fillRect(0, 0, 300, 75);
.parent {
  width: 300px;
  height: 300px;
  align-items: center;
  justify-content: center;
  display: flex;
  flex-direction: column;
  background-color: #6EE2F5;
}
.child {
  width: 300px;
  height: 75px;
  border: 1px solid red;
  background-image: linear-gradient(75.69deg, red, blue);
}
#canvas {
  width: 300px;
  height: 75px;
  border: 1px solid green;
}
<div class="parent">
<div class="child"></div>
<canvas id="canvas" width=300 height=75/>
</div>

这是一个交互式演示

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

function update() {
 var H = $('[name=h]').val();
 var W = $('[name=w]').val();
 $('.child').css('height',H);
 $('.child').css('width',W);
 $('canvas').attr("width", W);
 $('canvas').attr("height", H);
 var angle = Math.atan(W/H) 
 $('.child').css("--a", (angle * 180 / Math.PI)+"deg");

 var grd = ctx.createLinearGradient(0, H, W, 0);
 grd.addColorStop(0.4, "red");
 grd.addColorStop(0.6, "blue"); 
 ctx.fillStyle = grd;
 ctx.fillRect(0, 0, W, H);

}
$('input').change(update);
update();
.child {
  border: 1px solid;
  background-image: linear-gradient(var(--a), red 40%, blue 60%);
}
#canvas {
  border: 1px solid green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
W: <input type="number" name="w" step="1" value="300">
H: <input type="number" name="h" step="1" value="75">
<div class="child"></div>
<canvas id="canvas" width=300 height=75/>

【讨论】:

    【解决方案2】:

    只需将to right top 替换为to right。如果将其设置为to right top,则linear-gradient() 具有一定程度的应用,因为它以左下角为起点,向上延伸到矩形的右上角。

    var c = document.getElementById("canvas");
    var ctx = c.getContext("2d");
    
    var grd = ctx.createLinearGradient(0, 75, 300, 0);
    grd.addColorStop(0, "red");
    grd.addColorStop(1, "blue");
    
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, 300, 75);
    .parent {
      width: 300px;
      height: 300px;
      align-items: center;
      justify-content: center;
      display: flex;
      flex-direction: column;
      background-color: #6EE2F5;
    }
    
    .child {
      width: 300px;
      height: 75px;
      border: 1px solid red;
      background-image: linear-gradient(to right, red, blue);
    }
    
    #canvas {
      width: 300px;
      height: 75px;
      border: 1px solid green;
    }
    <div class="parent">
      <div class="child"></div>
      <canvas id="canvas" width=300 height=75/>
    </div>

    【讨论】:

    • 感谢您的回答,但是我的要求(右上对角线)有什么确切的解决方案吗?我正是需要那个。
    • 但是为什么在需要替代结果的同时需要使用该关键字?您正在玩任何黑客马拉松吗? :)
    • 我在 react 项目中使用它作为组件,所以元素的大小不是固定的,会动态变化,渐变应该适用于任何矩形。
    • 因为它以左下角为起点,向上延伸到矩形的右上角。 --> 如果是这样,这不是真的case 那么OP应该有正确的结果
    • @TemaniAfif 那你能更新答案吗?我不得不将此作为参考:prnt.sc/oyk1hb 如果 MDN 错误或我错了,请通过编辑更正我们俩。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多