我正在寻找在Canvas上绘制心形的形状。我发现了不同的数学方程式,但是我无法将它们中的任何一个转换为可以在onDraw方法中实现的代码。我希望在这里拥有与这种形状相似的心形:
我所处的形状方程式:
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9BdDdXOC5wbmcifQ==” alt =“在此处输入图像描述”>
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9yWllKdS5qcGcifQ==” alt =“在此处输入图像描述”>
Android绘图api不提供用于绘制任意方程曲线的工具。如果您愿意偏离为心脏找到的特定功能形式,则可以使用api支持的三次贝塞尔曲线绘制心脏(没有颜色效果)。您将创建一个Path
,然后使用其cubicTo
方法添加曲线截面。然后,您将使用cubicTo
渲染Path
。
[要使用三次贝塞尔曲线获得心脏形状,请查看Canvas#drawPath
(碰巧是在JavaScript中,但该想法很容易移植到Android)。
我不确定在心形中创建颜色渐变的最佳方法是什么。我的建议是使用贝塞尔曲线定义心脏的内部和外部边界,并将其设置为Canvas#drawPath
的裁剪区域。然后,您可以使用this example进行渐变填充以限制绘制渐变的位置。
Paint
Paint
public class HeartShape extends FrameLayout {
private Paint paint;
public HeartShape(@NonNull Context context) {
super(context);
init();
}
private void init() {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE);
setWillNotDraw(false);
}
public HeartShape(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public HeartShape(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public HeartShape(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
@Override
protected void onDraw(Canvas canvas) {
Path path = createHeartPath(canvas.getClipBounds().right,canvas.getClipBounds().bottom);
canvas.drawPath(path,paint);
super.onDraw(canvas);
}
private Path createHeartPath(int width, int height) {
Path path = new Path();
path.moveTo(0,height/3f);
path.lineTo(width,height/3f);
path.moveTo(width/2f,0f);
path.lineTo(width/2f,height);
float pX = width/2f;
float pY = (height/100f)*33.33f;
float x1 = (width/100f)*50;
float y1 = (height/100f)*5;
float x2 = (width/100f)*90;
float y2 = (height/100f)*10;
float x3 = (width/100f)*90;
float y3 = (height/100f)*33.33f;
path.moveTo(pX,pY);
path.cubicTo(x1, y1, x2, y2, x3, y3);
path.moveTo(x3,pY);
x1 = (width/100f)*90;
y1 = (height/100f)*55f;
x2 = (width/100f)*65;
y2 = (height/100f)*60f;
x3 = (width/100f)*50;
y3 = (height/100f)*90f;
path.cubicTo(x1, y1, x2, y2, x3, y3);
// path.lineTo(pX,pY);
x1 = (width/100f)*50;
y1 = (height/100f)*5;
x2 = (width/100f)*10;
y2 = (height/100f)*10;
x3 = (width/100f)*10;
y3 = (height/100f)*33.33f;
path.moveTo(pX,pY);
path.cubicTo(x1, y1, x2, y2, x3, y3);
path.moveTo(x3,pY);
x1 = (width/100f)*10;
y1 = (height/100f)*55f;
x2 = (width/100f)*35f;
y2 = (height/100f)*60f;
x3 = (width/100f)*50f;
y3 = (height/100f)*90f;
path.cubicTo(x1, y1, x2, y2, x3, y3);
//path.lineTo(pX,pY);
path.moveTo(x3,y3);
path.close();
return path;
}
}
删除绘图线代码并设置Output
paint.setStyle(Style.FILL);
我们可以修改private Path createHeartPath(int width, int height) {
Path path = new Path();
//path.moveTo(0,height/3f);
//path.lineTo(width,height/3f);
//path.moveTo(width/2f,0f);
//path.lineTo(width/2f,height);
float pX = width/2f;
float pY = (height/100f)*33.33f;
float x1 = (width/100f)*50;
float y1 = (height/100f)*5;
float x2 = (width/100f)*90;
float y2 = (height/100f)*10;
float x3 = (width/100f)*90;
float y3 = (height/100f)*33.33f;
path.moveTo(pX,pY);
path.cubicTo(x1, y1, x2, y2, x3, y3);
path.moveTo(x3,pY);
x1 = (width/100f)*90;
y1 = (height/100f)*55f;
x2 = (width/100f)*65;
y2 = (height/100f)*60f;
x3 = (width/100f)*50;
y3 = (height/100f)*90f;
path.cubicTo(x1, y1, x2, y2, x3, y3);
path.lineTo(pX,pY);
x1 = (width/100f)*50;
y1 = (height/100f)*5;
x2 = (width/100f)*10;
y2 = (height/100f)*10;
x3 = (width/100f)*10;
y3 = (height/100f)*33.33f;
path.moveTo(pX,pY);
path.cubicTo(x1, y1, x2, y2, x3, y3);
path.moveTo(x3,pY);
x1 = (width/100f)*10;
y1 = (height/100f)*55f;
x2 = (width/100f)*35f;
y2 = (height/100f)*60f;
x3 = (width/100f)*50f;
y3 = (height/100f)*90f;
path.cubicTo(x1, y1, x2, y2, x3, y3);
path.lineTo(pX,pY);
path.moveTo(x3,y3);
path.close();
return path;
}
方法的这种逻辑/绘图物理学,并获得更好的输出,欢迎提出新的建议和更改。