2013-08-22 3 views
0

Je porte Skycons à Android et j'ai la plupart d'entre eux travaillent, sauf la lune utilise HTML5 Canvas.arc avec l'argument antihoraire.Portage HTML5 Canvas.arc à Android et antihoraire

J'ai essayé de mettre en œuvre cette façon:

RectF rect = new RectF(); 

public void arcR(Path path, float x, float y, float radius, double startAngle, double endAngle, boolean anticlockwise){ 
    // Set bounds 
    rect.set(x - radius, y - radius, x + radius, y + radius); 

    // Convert to degrees 
    startAngle = Math.toDegrees(startAngle); 
    endAngle = Math.toDegrees(endAngle); 

    if(anticlockwise){ 
     startAngle = 360 - startAngle; 
     endAngle = 360 - endAngle; 
    } 

    endAngle = endAngle - startAngle; 

    path.addArc(rect, (float)startAngle, (float)endAngle); 
} 

Je ne pense pas que j'ai mis en sens inverse des aiguilles correctement, comme sur mon appareil dessin la lune (basé sur Skycons) ressemble à ceci:

Screenshot

+0

il n'y a aucune notion de droite et contre une montre en toile android parce que le signe de l'angle de balayage définit si elle est dans le sens horaire ou anti-horaire. – njzk2

+0

@ njzk2 Je suis conscient de cela, mais HTML5 le fait. –

Répondre

5

Pour contre les arcs dans le sens horaire, l'angle de balayage doit être négatif

float sweepAngle = ((endAngle + 360) - startAngle) % 360; 
if (anticlockwise) { 
    sweepAngle = sweepAngle - 360; 
} 
path.addArc(rect, startAngle, sweepAngle); 
+1

Pourriez-vous ajouter quelques explications? – Undo

0
double sweepAngle = endAngle - startAngle; 
startAngle = 360 - endAngle; 
path.addArc(rect, (float)startAngle, (float)sweepAngle); 
+0

Pas de dés. Je n'arrive pas à faire fonctionner les graphiques de la bonne façon. Il fonctionne partiellement, sauf que la lune apparaît à la mauvaise extrémité: G –

+0

Le code que j'ai posté sert à dessiner counterClockwise de startAngle à endAngle en utilisant path.addArc. J'ai supposé '(endAngle> startAngle) && (endAngle == endAngle% 360) && (startAngle == startAngle% 360)' Cela fonctionne dans mon test. Quand vous dites «dans le bon sens», que voulez-vous dire exactement? Peut-être serais-je en mesure de vous aider si vous fournissiez plus de détails. –

+0

J'essaye de porter Skycons qui dessine tout image par image dans une toile HTML5 et je n'ai aucune idée de la façon dont elle génère les angles pour l'icône de la lune. –

0

pour tracer une ligne de découpe comme vous devez trouver le centre du second cercle. J'ai supposé que le rayon du cercle de découpe serait le même que dans le cercle d'origine, mais bien sûr vous pouvez changer cela.

S'il vous plaît essayer ce code:

private void drawMoon(Path path, float x, float y, float radius, float startAngle, float endAngle) { 

    float sweepAngle = endAngle - startAngle; 

    float x1 = (float) (x + radius * Math.cos(Math.toRadians(startAngle))); 
    float y1 = (float) (y + radius * Math.sin(Math.toRadians(startAngle))); 

    float x2 = (float) (x + radius * Math.cos(Math.toRadians(endAngle))); 
    float y2 = (float) (y + radius * Math.sin(Math.toRadians(endAngle))); 

    float x3 = (x1 + x2)/2; 
    float y3 = (y1 + y2)/2; 
    float q = (float) Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); 

    float r = radius; // cutout circle radius 
    float cx = (float) (x3 + Math.sqrt(r * r - (q/2) * (q/2)) * (y1 - y2)/q); 
    float cy = (float) (y3 + Math.sqrt(r * r - (q/2) * (q/2)) * (x2 - x1)/q); 

    path.rewind(); 

    rect.set(x - radius, y - radius, x + radius, y + radius); 
    path.addArc(rect, startAngle, sweepAngle); 

    rect.set(cx - r, cy - r, cx + r, cy + r); 
    path.addArc(rect, (float) Math.toDegrees(Math.atan2(y1 - cy, x1 - cx)), 360 - sweepAngle); 

} 
0

différences entre l'arc de toile html5 et l'arc de toile Android:

  1. en html5/javascript vous donnez centerX, centerY, radius comme les 3 premiers arguments. Dans Android, vous donnez le rectangle entourant le cercle au lieu de ceux 3. C'est un peu plus lourd pour les cercles, mais est plus souple, comme vous pouvez le faire aussi ovales (ellipse)

  2. en javascript, vous donnez début angle, angle de fin, et booléen pour antihoraire comme arguments 4,5,6. Dans Android, vous donnez plutôt l'angle de départ et "l'angle de balayage". L'angle de balayage est la différence entre l'angle d'extrémité et l'angle de départ. Si vous voulez dans le sens antihoraire, donnez simplement un angle de balayage négatif. Javascript angles sont en radians, et dans android ils sont en degrés.

A titre d'illustration, voici quelques exemples de code qui dessine un C - figure en forme composé d'un arc long sur la gauche, et 3 courts arcs sur la droite, dont l'un dans le sens antihoraire.

JavaScript:

<!DOCTYPE HTML> 
<html> 
    <head> 
     <meta http-equiv="content-type" content="text/html" /> 
     <title>arcs</title> 
     <script type="text/javascript"> 
function initPage(){ 
    ctx = document.getElementById("canvas").getContext('2d'); 
    ctx.fillStyle = "blue"; 
    pi = Math.PI; 
    r = 100; 
    R = 3 * r; 
    padding = 5; 
    width = 2 * (R + padding); 
    height = width; 
    centerX = padding + width/2; 
    centerY = padding + height/2; 
    ctx.beginPath(); 
    ctx.arc(centerX, centerY,  R, pi/2, 3*pi/2, false); 
    ctx.arc(centerX, centerY - 2*r, r, 3*pi/2, pi/2, false); 
    ctx.arc(centerX, centerY,  r, 3*pi/2, pi/2, true); 
    ctx.arc(centerX, centerY + 2*r, r, 3*pi/2, pi/2, false); 
    ctx.fill(); 
} 
     </script>   
    </head> 

    <body onload="initPage();"> 
     <canvas id="canvas" width="610" height="610"></canvas> 
    </body> 
</html> 

android:

import android.app.Activity; 
import android.graphics.Bitmap; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Path; 
import android.graphics.RectF; 
import android.graphics.drawable.BitmapDrawable; 
import android.os.Bundle; 
import android.widget.ImageView; 

public class MainActivity extends Activity { 

    private void drawToImageView(ImageView iv){ 
     Paint paint = new Paint(); 
     paint.setStyle(Paint.Style.FILL); 
     paint.setColor(Color.BLUE); 
     Path path = new Path(); 
     int radius = 140; 
     int Radius = 3 * radius; 
     int padding = 5; 
     int width = 2 * (Radius + padding); 
     int height = width; 
     Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
     Canvas canvas = new Canvas(bm); 
     float a = 90f; 
     float b = 3*a; 
     float pi = 2*a; 
     float _radius = (float)radius; 
     float _Radius = (float)Radius; 
     float centerX = padding + width/2; 
     float centerY = padding + height/2; 
     path.addArc(circRect(centerX, centerY,    _Radius), a, pi); 
     path.addArc(circRect(centerX, centerY - 2*_radius, _radius), b, pi); 
     path.addArc(circRect(centerX, centerY,    _radius), b, -pi); 
     path.addArc(circRect(centerX, centerY + 2*_radius, _radius), b, pi); 
     canvas.drawPath(path, paint); 
     iv.setImageDrawable(new BitmapDrawable(getResources(), bm)); 
    } 
    private RectF circRect(float centerX, float centerY, float radius){ 
     float left = centerX - radius; 
     float right = centerX + radius; 
     float top = centerY - radius; 
     float bottom = centerY + radius; 
     return new RectF(left, top, right, bottom); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     ImageView iv = (ImageView)findViewById(R.id.myImageView); 
     drawToImageView(iv); 
    } 
}