简体   繁体   English

如何用起始文本绘制圆弧

[英]How to draw arc with starting text

I have to create an arc using canvas and add text in the start position of arc, but it does not look proper.我必须使用画布创建一个圆弧并在圆弧的起始位置添加文本,但它看起来不正确。 Please see the image my text is cut off the top position, My text display linear not curve.请看图片我的文字在顶部位置被切断,我的文字显示线性而不是曲线。

在此处输入图片说明

My Code我的代码

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mRect == null) {
            centerX = getMeasuredWidth() / 2;
            centerY = getMeasuredHeight() / 2;
            radius = Math.min(centerX, centerY);
            int startTop = STROKE_WIDTH / 2;
            mRect = new RectF(STROKE_WIDTH / 2, STROKE_WIDTH / 2, (2 * radius - startTop), (2 * radius - startTop));
            canvas.drawArc(mRect, 270, 270, false, mDegreesPaint);

            Paint paint = new Paint();

            paint.setColor(Color.TRANSPARENT);
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
            paint.setTextAlign(Paint.Align.LEFT);
            paint.setLinearText(true);
            canvas.drawPaint(paint);

            paint.setColor(getResources().getColor(R.color.colorPrimaryDark));
            paint.setTextSize(30);

            //float radius = 300;
                float x = (float)(radius * Math.cos(mRect.width() * Math.PI)) + getWidth()/2 - 10;
                float y = (float)(radius * Math.sin(mRect.height() * Math.PI )) + getHeight()/2 - 20;

            Path addArc = new Path();
            addArc.arcTo(mRect, 250, 270);

            canvas.drawTextOnPath("text",addArc, 0, 0 , paint);




        }
    }

Look at this method:看看这个方法:

public void drawTextOnPath (String text, 
                Path path, 
                float hOffset, 
                float vOffset, 
                Paint paint)

Here, vOffset (float) is the distance above(-) or below(+) the path to position the text.此处,vOffset (float) 是放置文本的路径上方(-) 或下方(+) 的距离。

And, hOffset (float) is the distance along the path to add to the text's starting position.并且,hOffset (float) 是沿路径添加到文本起始位置的距离。

Try changing values in vOffset and hOffset to position text according to the requirement.尝试更改 vOffset 和 hOffset 中的值以根据要求定位文本。

Adjusting Arc thickness and text size:调整圆弧粗细和文字大小:

Either use this method paint.setStrokeWidth(x);要么使用此方法paint.setStrokeWidth(x); to increase your arc thickness or decrease the size of text in this paint.setTextSize(30);在此paint.setTextSize(30);增加弧线厚度或减小文本大小paint.setTextSize(30); . .

That if (mRect == null) line is going to mess you up if the view gets redrawn. if (mRect == null)视图被重绘, if (mRect == null)行会让你if (mRect == null) It will turn blank.它会变成空白。 You should instantiate the Rectangle at its declaration and modify its dimensions in onDraw().您应该在其声明处实例化 Rectangle 并在 onDraw() 中修改其尺寸。 I would also set up your paint outside your draw method to make it faster if this view has to get redrawn in an animation.如果必须在动画中重绘此视图,我还会在 draw 方法之外设置您的绘画,以使其更快。

I'm not sure what the x and y are for in your code, but whatever you were calculating most likely doesn't make sense since you have the height and width inside the trig functions.我不知道什么是xy是在你的代码,但无论你是计算最有可能的,因为你有三角函数里面的高度和宽度是没有意义的。

So you got the arc to draw inside the rectangle by subtracting half its stroke width.因此,您可以通过减去其笔划宽度的一半来在矩形内绘制圆弧。 Then you use this same rectangle to make the arc for the text to sit on.然后你使用这个相同的矩形来制作文本的弧线。 Text is drawn at its baseline (the bottom of letters that don't hang down like g, j, p, and y).文本在其基线处(不像 g、j、p 和 y 那样下垂的字母底部)绘制。

So in your case, you probably want the text to fit inside the view bounds, so you should make an arc that is smaller than the view by the size of your text instead of half the stroke width that you used for your arc.所以在你的情况下,你可能希望文本适合视图边界,所以你应该制作一个比视图小你的文本大小的弧,而不是你用于弧的笔划宽度的一半。

I also see an error in how you place your rectangle for the circular arc.我还看到了如何为圆弧放置矩形的错误。 It is located via bottom left corner of the view.它位于视图的左下角。 So if you view is not square, it will be off center.所以如果你的视野不是方形的,它就会偏离中心。 You should located based on the center point.您应该根据中心点定位。

Since you do this calculation twice, you can write a function for it.由于您进行了两次此计算,因此您可以为它编写一个函数。

private val mRect = RectF()
private val mTextPaint = Paint().apply {
    color = resources.getColor(R.color.colorPrimaryDark)
    antiAlias = true
    style = Paint.Style.FILL_AND_STROKE
    textAlign = Paint.Align.LEFT
    linearText = true
}

private fun updateCenteredRect(rect: RectF, inset: Int) {
    val centerX = measuredWidth / 2
    val centerY = measuredHeight / 2
    val radius = min(centerX, centerY) - inset
    rect.set(centerX - radius, centerY - radius, radius * 2, radius * 2)
}

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    updateCenteredRect(mRect, STROKE_WIDTH / 2)
    canvas.drawArc(mRect, 270, 270, false, mDegreesPaint)

    val textSize = 30 // You should calculate this based on screen density or it will look too big or small on some devices
    mTextPaint.textSize = textSize
    updateCenteredRect(mRect, textSize)
    Path addArc = new Path().apply {
        arcTo(mRect, 250, 270)
    }
    canvas.drawTextOnPath("text", addArc, 0, 0, mTextPaint)
}

I wrote this without really noticing your original code is in Java.我写这篇文章时并没有真正注意到你的原始代码是用 Java 编写的。 I found your question through the Kotlin tag.我通过 Kotlin 标签找到了您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM