首页 > 解决方案 > HTML css 线性渐变未按预期工作

问题描述

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

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

linear-gradient我做了一个小提琴来展示 css和 canvas之间的差异create createLinearGradient。请检查这个小提琴链接

例子

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

标签: htmlcsshtml5-canvaslinear-gradients

解决方案


这是设计使然。您可以在此处阅读更多信息:https ://drafts.c​​sswg.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/>


推荐阅读