Dessiner des segments de cercle ou donut
J'ai essayé de trouver un moyen de dessiner des segments, comme illustré dans l'image suivante:
J'aimerais:
- dessiner le segment
- inclure des gradients
- inclure les ombres
- animer le dessin de 0 à n angle
J'ai essayé de le faire avec CGContextAddArc
et des appels similaires mais n'obtenant pas très loin.
Peut aider quelqu'un ?
- Vous pouvez poster ce que vous avez essayé? J'ai toujours pensé que le construit-dans les fonctions de dessin sont assez intuitif...
- Je sais que vous demander il y a longtemps et peut-être trouvé la solution. Mais vérifier mon code, peut-être se trouver quelque chose. github.com/sakrist/VBPieChart
- OP, pouvez-vous s'il vous plaît re-télécharger votre image? La question n'a pas de sens sans la voir. Thx! 🙂
Vous devez vous connecter pour publier un commentaire.
Il y a beaucoup de pièces à votre question.
Obtenir le chemin d'accès
De la création de la voie pour un segment ne devrait pas être trop dur. Il y a deux arcs et deux lignes droites. J'ai on l'a déjà expliqué comment vous pouvez décomposer un chemin comme celui donc je ne vais pas le faire ici. Au lieu de cela, je vais être de fantaisie et de créer le chemin de caresser un autre chemin. Bien sûr, vous pouvez lire le détail de la répartition et de construire le chemin de vous-même. L'arc je parle en caressant l'orange à l'arc à l'intérieur du gris pointillé résultat final.
À coup le chemin, nous avons d'abord besoin d'elle. qui est en fait aussi simple que déplacement à le point de départ et le dessin d'un arc de cercle autour du centre de l'angle en cours à l'angle que vous voulez que le segment de la couverture.
Ensuite quand vous avez (l'arc), vous pouvez créer un nouveau segment, en le caressant avec une certaine largeur. La trajectoire résultante va avoir les deux lignes droites et les deux arcs. La course se passe à partir du centre d'une distance égale vers l'intérieur et vers l'extérieur.
Dessin
Jusqu'à la prochaine est le dessin et il y a généralement deux choix principaux: Graphiques de Base dans
drawRect:
ou les calques de forme avec le Noyau de l'Animation. Graphiques de base va vous donner le plus de dessin puissant mais Core Animation va vous donner la meilleure performance d'animation. Comme les chemins sont impliqués pur Cora Animation ne fonctionne pas. Vous allez vous retrouver avec d'étranges artefacts. On peut cependant utiliser une combinaison de couches et Graphiques de Base par le dessin de la le contexte graphique de la couche.De remplissage et en se caressant le segment
Nous avons déjà la forme de base, mais avant de nous ajouter des dégradés et des ombres, il me fera une base de remplissage et de contour (vous disposez d'un trait noir dans votre image).
Qui va mettre quelque chose comme ceci sur l'écran
Ajoutant des ombres
Je vais changer l'ordre et de faire de l'ombre avant de le dégradé. Pour dessiner l'ombre, nous avons besoin de configurer une ombre pour le contexte et le tirage remplir la forme à dessiner avec l'ombre. Ensuite, nous avons besoin de restaurer le contexte (à l'ombre) et de l'avc de nouveau la forme.
À ce point, le résultat est quelque chose comme cela
Dessin le gradient de
Pour le dégradé, nous avons besoin d'un calque de dégradé. Je suis en train de faire un simple de deux couleurs gradient ici, mais vous pouvez le personnaliser tout ce que vous voulez. Pour créer le dégradé, nous avons besoin d'obtenir les couleurs et la couleur adéquate de l'espace. Ensuite, nous pouvons tracer le dégradé sur le dessus de la remplir (mais avant le coup). Nous avons également besoin de masquer le dégradé sur le même chemin qu'avant. Pour ce faire, nous clip le chemin.
Ce termine le dessin que nous avons actuellement ce résultat
Animation
Quand il s'agit de l'animation de la forme qu'il a tous été écrits avant: Animation des morceaux de Tarte à l'Aide d'un Custom CALayer. Si vous essayez de faire le dessin de simplement l'animation de la trajectoire de propriété que vous allez voir quelques vraiment funky déformation de la trajectoire au cours de l'animation. L'ombre et de gradient a été laissé intact pour des fins d'illustration seulement l'image ci-dessous.
Je vous suggère de prendre le code de dessin que j'ai posté dans cette réponse, et de l'adopter à l'animation de code à partir de cet article. Ensuite, vous devriez vous retrouver avec la ce que vous demandez.
De référence: le même dessin à l'aide de Core Animation
Plaine forme
Ajoutant des ombres
La couche a un peu d'ombre liées à des propriétés que c'est à vous de les personnaliser. Howerever vous devez définir la
shadowPath
propriété pour l'amélioration de la performance.Dessin le gradient de
Si nous avons tiré le gradient de maintenant, il serait au-dessus de la forme et non pas à l'intérieur. Non, nous ne pouvons pas avoir un dégradé de remplissage de la forme (je sais que vous avez été la pensée de celui-ci). Nous avons besoin de masquer le gradient de sorte qu'il aller à l'extérieur du segment. Pour cela nous avons créer un autre couche pour être le masque de ce segment. Il doit être une autre couche, la documentation est claire que le comportement est "undefined" si le masque est la partie de la couche de la hiérarchie. Puisque le masque du système de coordonnées est le même que celui de sous-couches à gradient, nous allons traduire le segment de la forme avant de l'installer.
Tout ce dont vous avez besoin est couvert dans le Quartz 2D Guide de Programmation. Je vous suggère de regarder à travers elle.
Cependant, il peut être difficile de mettre tout cela ensemble, donc je vais vous guider à travers elle. Nous allons écrire une fonction qui prend une taille et renvoie une image qui ressemble à peu près à l'un de vos segments:
Nous commençons la définition de la fonction comme ceci:
Nous aurons besoin d'une constante de l'épaisseur du segment:
et une constante pour la largeur de la ligne décrivant le segment:
et une constante pour la taille de l'ombre:
Ensuite, nous devons créer une image contexte dans lequel dessiner:
J'ai mis une accolade gauche sur la fin de la ligne, parce que j'aime un niveau supplémentaire de retrait pour me rappeler d'appeler
UIGraphicsEndImageContext
plus tard.Depuis beaucoup de fonctions dont nous avons besoin à l'appel sont des Graphiques de Base (aka Quartz 2D) de fonctions, de ne pas UIKit fonctions, nous devons obtenir de l'
CGContext
:Nous sommes maintenant prêts à vraiment commencer. Nous avons d'abord ajouter un arc pour le chemin d'accès. L'arc court le long du centre du segment nous voulons attirer l':
Maintenant, nous allons demander Graphiques de Base pour remplacer le chemin d'accès avec une “caresse”, version qui décrit le chemin d'accès. Nous avons d'abord définir l'épaisseur du trait à l'épaisseur de la nous voulons le segment d'avoir:
et nous avons défini la ligne de casquette style “bout à bout” de sorte que nous allons carré-off se termine:
Alors nous pouvons nous demander Graphiques de Base pour remplacer le chemin d'accès avec un caressa version:
Pour remplir ce chemin avec un dégradé linéaire, nous devons le dire Graphiques de Base à clip toutes les opérations à l'intérieur de la trajectoire. Cela permettra de faire des Graphiques de Base réinitialiser le chemin, mais nous allons avoir besoin de le chemin plus tard pour dessiner la ligne noire autour du bord. Donc, nous allons copier le chemin d'accès ici:
Puisque nous voulons que le segment de jeter une ombre, nous allons mettre l'ombre des paramètres avant de nous faire un dessin:
Nous allons à la fois de combler le segment (avec un dégradé) et d'accident vasculaire cérébral (pour dessiner le contour noir). Nous voulons une seule ombre pour les deux opérations. Nous dire Graphiques de Base qu'en commençant par une couche de transparence:
J'ai mis une accolade gauche sur la fin de la ligne, parce que j'aime avoir un niveau d'indentation pour me rappeler d'appeler
CGContextEndTransparencyLayer
plus tard.Puisque nous allons modifier le contexte du clip de la région pour le remplissage, mais nous ne voulons pas de saturation lorsque nous caresser le contour plus tard, nous avons besoin d'enregistrer l'état graphique:
J'ai mis une accolade gauche sur la fin de la ligne, parce que j'aime avoir un niveau d'indentation pour me rappeler d'appeler
CGContextRestoreGState
plus tard.Pour combler le chemin avec un dégradé, nous avons besoin de créer un gradient de l'objet:
Nous avons également besoin de trouver un point de départ et un point de fin du dégradé. Nous allons utiliser le chemin d'accès de la boîte englobante:
et nous allons la force du gradient à tirer horizontalement ou verticalement, selon la plus longue:
Maintenant, enfin, nous avons tout ce dont nous avons besoin pour tracer le dégradé. Nous avons d'abord clip pour le chemin d'accès:
Puis nous tracer le dégradé:
Alors nous pouvons libérer le gradient et de restaurer les sauvés de l'état graphique:
Quand nous l'avons appelé
CGContextClip
, Graphiques de Base réinitialiser le contexte du chemin. Le chemin n'est pas une partie de l'sauvé de l'état graphique; c'est pourquoi nous avons fait une copie plus tôt. Il est temps maintenant d'utiliser cette copie pour définir le chemin d'accès dans le contexte nouveau:Maintenant, nous pouvons avc le chemin, pour dessiner le contour noir du segment:
Ensuite nous dire Graphiques de Base pour mettre fin à la transparence de la couche. Cela permettra de regarder ce que nous avons dessiné et ajouter de l'ombre en-dessous:
Maintenant, nous sommes tous fait de dessin. Nous demandons UIKit pour créer un
UIImage
à partir de l'image contexte, détruire le contexte et le retour de l'image:Vous pouvez trouver le code tous ensemble dans ce gist.
C'est un Swift 3 version de Rob Mayoff de réponse. Il suffit de voir comment beaucoup plus efficace que ce langage est! Ce pourrait être le contenu d'un MView.swift fichier:
Appeler à partir d'un viewController comme ceci:
À faire de degrés en radians conversions j'ai créé la ° postfix opérateur. Ainsi, vous pouvez maintenant utiliser, par exemple, 45° et de ce fait la conversion à partir de 45 degrés en radians.
Cet exemple est pour Ints, les étendre également pour les types Float si vous en avez besoin:
Placer ce code dans un utilitaires swift fichier.