第 7 章练习:圆形与图片的比例

对应教程:07 距离绘图与比例修正
起始示例:圆与图片的比例修正,修改 07-aspect.js 和需要时的 07-aspect.html。

练习 1:先算清两个比例

一块正对相机的平面显示为 2:1,图片原始比例为 3:2。

**目标:**分别算出圆形修正时 UV 的 x 分量应乘多少,图片 cover 和 contain 的两个 scale 分量应是多少;说明 cover 会裁掉哪两个边、contain 会在哪两个边留白。

**完成标准:**能把“目标区域比例”和“原图比例”分开使用,并判断裁切与留白的方向。

练习 2:画一个不变形的圆环

**目标:**新增“比例修正的圆环”模式。外半径约 0.28,内半径约 0.17;改变平面宽高比时,圆环保持圆形且厚度一致。

**要求:**复用比例修正后的 point;用两个软圆遮罩相减。新增下拉选项,不改变原有圆形与图片模式。

**完成标准:**宽平面和窄平面上都是圆环,而不是椭圆环;圆心仍在平面中心。

<details> <summary>提示</summary>

先做外圆,再做更小的内圆;外遮罩减去内遮罩。

</details>

练习 3:让 cover 从顶部裁切

**目标:**新增一种 cover 模式。当目标区域比图片更宽,竖直方向需要裁切时,保留原图顶部,裁掉更多底部内容。

**要求:**继续使用原 coverScale,只改变图片 UV 的 y 方向映射;新增模式。图片比例与图中太阳形状不能改变。

**完成标准:**目标比例设为 2.0 时,普通 cover 居中裁上下,新模式优先保留顶部的 LEFT / RIGHT 标签;目标比例等于图片比例时两模式相同。

<details> <summary>提示</summary>

让目标顶部 vUv.y == 1.0 始终映射到原图顶部 imageUv.y == 1.0。

</details>

参考解答


<a id=“reference-answers”></a>

第 7 章练习参考解答

对应练习:圆形与图片的比例。

练习 1:先算清两个比例

目标区域 A = 2.0,原图 B = 1.5。

这里 A 来自平面,B 来自图片,两个比例不可互换。

练习 2:画一个不变形的圆环

在 07-aspect.html 的模式列表中增加:

<option value="5">圆:修正比例的圆环</option>

在 07-aspect.js 的片元着色器中,把圆形分支的条件改为:

if ( uMode <= 1 || uMode == 5 ) {

圆形分支中,把修正比例的条件改为:

if ( uMode == 1 || uMode == 5 ) {
  point.x *= uTargetAspect;
}

再将原有的 radius、circle 和 color = mix(...) 三行替换为:

float distanceToCenter = length( point );
float outer = 1.0 - smoothstep( 0.275, 0.285, distanceToCenter );

if ( uMode == 5 ) {
  float inner = 1.0 - smoothstep( 0.165, 0.175, distanceToCenter );
  color = mix( color, vec3( 0.95, 0.42, 0.17 ), outer - inner );
} else {
  color = mix( color, vec3( 0.95, 0.42, 0.17 ), outer );
}

原有的图片 else 分支保持不变。外圆半径约 0.28,内圆约 0.17;两者都在同一修正坐标中计算,所以圆环厚度也按目标区域的高度度量。

练习 3:让 cover 从顶部裁切

在 07-aspect.html 中增加:

<option value="6">图片:cover 顶部对齐</option>

先完成练习 2,或单独在原示例上使用模式编号 5。把图片分支中的 if (uMode == 3) 改为 if (uMode == 3 || uMode == 6);在现有居中 imageUv 计算后追加:

if ( uMode == 6 ) {
  imageUv.y = 1.0 - ( 1.0 - vUv.y ) * coverScale.y;
}

完整关系是:目标顶部 vUv.y = 1.0 映射到原图 imageUv.y = 1.0;若 coverScale.y = 0.75,目标底部映射到原图 y 的 0.25,于是只裁原图底部的 0.0~0.25。目标和原图等比例时 coverScale.y = 1.0,新旧映射相同。由于练习 2 把模式 5 用于圆环,顶部对齐模式取编号 6。