如何解决如何在 SwiftUI 中缩放路径?
我在根据我的目的缩放 Path
时遇到了一些问题。我从 API 获取了一些我想在我的视图中绘制的 SVG 数据。为了简单起见,让我们说这是我从 API 中得到的:
extension UIBezierPath {
static var rectangle: UIBezierPath {
let path = UIBezierPath()
path.move(to: CGPoint(x: 200,y: 100))
path.addLine(to: CGPoint(x: 100,y: 300))
path.addLine(to: CGPoint(x: 300,y: 300))
path.addLine(to: CGPoint(x: 200,y: 100))
return path
}
}
当我在视图中显示此路径时,一切正常。
由于来自 API 的 SVG 坐标具有偏移量并且有时比 iPhone 的显示屏大,我需要将它们按比例缩小/放大到特定大小并将它们居中显示在我的视图中。为了做到这一点,我尝试了这种转换:
struct ScaledShapeView: Shape {
let bezier: UIBezierPath
func path(in rect: CGRect) -> Path {
let bounds = bezier.bounds
let scaleX = rect.size.width/bounds.size.width
let scaleY = rect.size.height/bounds.size.height
let scale = max(scaleX,scaleY)
return Path(bezier.cgPath).applying(CGAffineTransform(scaleX: scale,y: scale))
}
}
并在我看来使用它:
struct TestView: View {
var body: some View {
ScaledShapeView(bezier: .rectangle)
.frame(width: 100,height: 100)
}
}
但这是我的结果:
我不确定到底是什么问题。我想实现形状在框架的中间。
@SwiftPunk:
当我尝试
var body: some View {
Path(UIBezierPath.logo1.cgPath)
.frame(width: 100,height: 100)
.scaleEffect(CGSize(width: 0.5,height: 0.5))
}
我得到了这个结果:
解决方法
标准化每个 X 和 Y 位置以绘制 0 和 1 之间的点,其中 0 表示顶边或前缘,1 表示底边或后缘。
此外,我们将找到宽度和高度的最小值,以便我们可以按比例缩放 Bezier 路径,使其在增长时保持相同的形状。
import java.awt.*;
import java.util.Scanner;
import javax.swing.*;
public class Colors {
public static final int CLI = 0,GUI = 1;
private Color color = Color.RED;//default value
private static final int CYCLE_TIME = 1000;
private static final String[] colorsNames = {"Red","Green","Blue"};
public Colors(int userInputBy) {
if(userInputBy == CLI){
cliInput();
}else if (userInputBy == GUI){
guiInput();
}//or else use default
changing();
}
private void guiInput() {
//use JOptionPane to get input from user
JSpinner colorSpinner = new JSpinner(new SpinnerListModel(colorsNames));
int answer = JOptionPane.showOptionDialog(null,colorSpinner,"Select color",JOptionPane.OK_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE,null,null);
String colorName ="";
if (answer == JOptionPane.OK_OPTION) {// user selected a color
colorName = (String) colorSpinner.getValue();
}
colorByName(colorName);
}
private void cliInput() {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter Color Choice (Red/Green/Blue)");
String colorName = scanner.nextLine();
scanner.close();
colorByName(colorName);
}
private void colorByName(String colorName) {
if (colorName.equals(colorsNames[0])) {
color = Color.RED;
} else if (colorName.equals(colorsNames[1])) {
color = Color.GREEN;
} else if (colorName.equals(colorsNames[2])) {
color = Color.BLUE;
}
}
private void changing() {
JFrame frame = newJFrame("Color Changer // Main");
ChangingColorPane ccp = new ChangingColorPane(color);
frame.add(ccp);
frame.pack();
frame.setVisible(true);
//use swing time to animate
Timer timer = new Timer(CYCLE_TIME,e->{
changeColor();
ccp.setBgColor(color);
frame.repaint();
});
timer.start();
}
private void changeColor() {
if (color.equals(Color.RED)) {
color = Color.GREEN;
} else if (color.equals(Color.GREEN)) {
color = Color.BLUE;
} else if (color.equals(Color.BLUE)) {
color = Color.RED;
}
}
//do custom painting on a JPanel
class ChangingColorPane extends JPanel{
private static final int W = 400,H = 500;
private Color bgColor;
public ChangingColorPane(Color bgColor) {
this.bgColor = bgColor;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(bgColor);
g.fillRect(0,getWidth(),getHeight());
}
@Override
public Dimension preferredSize() {
return new Dimension(W,H);
}
public void setBgColor(Color bgColor) {
this.bgColor = bgColor;
}
}
public static void main(String[] args) {
new Colors(1);
}
private static JFrame newJFrame(String title) {
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.setUndecorated(true);
return frame;
}
}
输出-:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。