- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我希望我的节点以正弦曲线波传播,我尝试将其用于 CGPath。如何创建遵循正弦曲线的 CGPath?除了手动找到曲线上的点之外,还有其他方法吗,或者我可以只传入一个正弦函数吗?
let action = SKAction.followPath(<the sine path>, asOffset: true, orientToPath: true, duration: 5)
这可以通过 Bezier Paths 完成,然后转换为 CGPaths 吗?谢谢。
最佳答案
不,没有从函数构建路径的内置方法,但您可以轻松编写自己的方法。在 Swift 3 中:
/// Build path within rectangle
///
/// Given a `function` that converts values between zero and one to another values between zero and one, this method will create `UIBezierPath` within `rect` using that `function`.
///
/// - parameter rect: The `CGRect` of points on the screen.
///
/// - parameter count: How many points should be rendered. Defaults to `rect.size.width`.
///
/// - parameter function: A closure that will be passed an floating point number between zero and one and should return a return value between zero and one as well.
private func path(in rect: CGRect, count: Int? = nil, function: (CGFloat) -> (CGFloat)) -> UIBezierPath {
let numberOfPoints = count ?? Int(rect.size.width)
let path = UIBezierPath()
path.move(to: convert(point: CGPoint(x: 0, y: function(0)), in: rect))
for i in 1 ..< numberOfPoints {
let x = CGFloat(i) / CGFloat(numberOfPoints - 1)
path.addLine(to: convert(point: CGPoint(x: x, y: function(x)), in: rect))
}
return path
}
/// Convert point with x and y values between 0 and 1 within the `CGRect`.
///
/// - parameter point: A `CGPoint` value with x and y values between 0 and 1.
/// - parameter rect: The `CGRect` within which that point should be converted.
private func convert(point: CGPoint, in rect: CGRect) -> CGPoint {
return CGPoint(
x: rect.origin.x + point.x * rect.size.width,
y: rect.origin.y + rect.size.height - point.y * rect.size.height
)
}
所以,让我们传递一个函数,当它在 rect
的 width
上前进时,它会执行一条正弦曲线:
func sinePath(in rect: CGRect, count: Int? = nil) -> UIBezierPath {
// note, since sine returns values between -1 and 1, let's add 1 and divide by two to get it between 0 and 1
return path(in: rect, count: count) { (sin($0 * .pi * 2.0) + 1.0) / 2.0 }
}
注意,上面假设你想从左到右遍历,构建函数定义的路径。您还可以做更多的参数化再现:
/// Build path within rectangle
///
/// Given a `function` that converts values between zero and one to another values between zero and one, this method will create `UIBezierPath` within `rect` using that `function`.
///
/// - parameter rect: The `CGRect` of points on the screen.
///
/// - parameter count: How many points should be rendered. Defaults to `rect.size.width` or `rect.size.width`, whichever is larger.
///
/// - parameter function: A closure that will be passed an floating point number between zero and one and should return a `CGPoint` with `x` and `y` values between 0 and 1.
private func parametricPath(in rect: CGRect, count: Int? = nil, function: (CGFloat) -> (CGPoint)) -> UIBezierPath {
let numberOfPoints = count ?? max(Int(rect.size.width), Int(rect.size.height))
let path = UIBezierPath()
let result = function(0)
path.move(to: convert(point: CGPoint(x: result.x, y: result.y), in: rect))
for i in 1 ..< numberOfPoints {
let t = CGFloat(i) / CGFloat(numberOfPoints - 1)
let result = function(t)
path.addLine(to: convert(point: CGPoint(x: result.x, y: result.y), in: rect))
}
return path
}
然后你可以使用正弦曲线修改x
坐标,并增加y
:
func verticalSinePath(in rect: CGRect, count: Int? = nil) -> UIBezierPath {
// note, since sine returns values between -1 and 1, let's add 1 and divide by two to get it between 0 and 1
return parametricPath(in: rect, count: count) { CGPoint(
x: (sin($0 * .pi * 2.0) + 1.0) / 2.0,
y: $0
) }
}
这样做的好处是你现在也可以定义任何你想要的路径,例如一个螺旋:
func spiralPath(in rect: CGRect, count: Int? = nil) -> UIBezierPath {
return parametricPath(in: rect, count: count) { t in
let r = 1.0 - sin(t * .pi / 2.0)
return CGPoint(
x: (r * sin(t * 10.0 * .pi * 2.0) + 1.0) / 2.0,
y: (r * cos(t * 10.0 * .pi * 2.0) + 1.0) / 2.0
)
}
}
以下是上述的 Swift 2 版本:
/// Build path within rectangle
///
/// Given a `function` that converts values between zero and one to another values between zero and one, this method will create `UIBezierPath` within `rect` using that `function`.
///
/// - parameter rect: The `CGRect` of points on the screen.
///
/// - parameter count: How many points should be rendered. Defaults to `rect.size.width`.
///
/// - parameter function: A closure that will be passed an floating point number between zero and one and should return a return value between zero and one as well.
private func path(in rect: CGRect, count: Int? = nil, function: (CGFloat) -> (CGFloat)) -> UIBezierPath {
let numberOfPoints = count ?? Int(rect.size.width)
let path = UIBezierPath()
path.moveToPoint(convert(point: CGPoint(x: 0, y: function(0)), rect: rect))
for i in 1 ..< numberOfPoints {
let x = CGFloat(i) / CGFloat(numberOfPoints - 1)
path.addLineToPoint(convert(point: CGPoint(x: x, y: function(x)), rect: rect))
}
return path
}
/// Convert point with x and y values between 0 and 1 within the `CGRect`.
///
/// - parameter point: A `CGPoint` value with x and y values between 0 and 1.
/// - parameter rect: The `CGRect` within which that point should be converted.
private func convert(point point: CGPoint, rect: CGRect) -> CGPoint {
return CGPoint(
x: rect.origin.x + point.x * rect.size.width,
y: rect.origin.y + rect.size.height - point.y * rect.size.height
)
}
func sinePath(in rect: CGRect, count: Int? = nil) -> UIBezierPath {
// note, since sine returns values between -1 and 1, let's add 1 and divide by two to get it between 0 and 1
return path(in: rect, count: count) { (sin($0 * CGFloat(M_PI * 2.0)) + 1.0) / 2.0 }
}
/// Build path within rectangle
///
/// Given a `function` that converts values between zero and one to another values between zero and one, this method will create `UIBezierPath` within `rect` using that `function`.
///
/// - parameter rect: The `CGRect` of points on the screen.
///
/// - parameter count: How many points should be rendered. Defaults to `rect.size.width`.
///
/// - parameter function: A closure that will be passed an floating point number between zero and one and should return a `CGPoint` with `x` and `y` values between 0 and 1.
private func parametricPath(in rect: CGRect, count: Int? = nil, function: (CGFloat) -> (CGPoint)) -> UIBezierPath {
let numberOfPoints = count ?? max(Int(rect.size.width), Int(rect.size.height))
let path = UIBezierPath()
let result = function(0)
path.moveToPoint(convert(point: CGPoint(x: result.x, y: result.y), rect: rect))
for i in 1 ..< numberOfPoints {
let t = CGFloat(i) / CGFloat(numberOfPoints - 1)
let result = function(t)
path.addLineToPoint(convert(point: CGPoint(x: result.x, y: result.y), rect: rect))
}
return path
}
func verticalSinePath(in rect: CGRect, count: Int? = nil) -> UIBezierPath {
// note, since sine returns values between -1 and 1, let's add 1 and divide by two to get it between 0 and 1
return parametricPath(in: rect, count: count) { CGPoint(
x: (sin($0 * CGFloat(M_PI * 2.0)) + 1.0) / 2.0,
y: $0
) }
}
func spiralPath(in rect: CGRect, count: Int? = nil) -> UIBezierPath {
return parametricPath(in: rect, count: count) { t in
let r = 1.0 - sin(t * CGFloat(M_PI_2))
return CGPoint(
x: (r * sin(t * 10.0 * CGFloat(M_PI * 2.0)) + 1.0) / 2.0,
y: (r * cos(t * 10.0 * CGFloat(M_PI * 2.0)) + 1.0) / 2.0
)
}
}
关于sprite-kit - 如何创建波浪路径 Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34474274/
前言: 有时候,一个数据库有多个帐号,包括数据库管理员,开发人员,运维支撑人员等,可能有很多帐号都有比较大的权限,例如DDL操作权限(创建,修改,删除存储过程,创建,修改,删除表等),账户多了,管理
所以我用 Create React App 创建并设置了一个大型 React 应用程序。最近我们开始使用 Storybook 来处理和创建组件。它很棒。但是,当我们尝试运行或构建应用程序时,我们不断遇
遵循我正在创建的控件的代码片段。这个控件用在不同的地方,变量也不同。 我正在尝试编写指令来清理代码,但在 {{}} 附近插入值时出现解析错误。 刚接触 Angular ,无法确定我错过了什么。请帮忙。
我正在尝试创建一个 image/jpeg jax-rs 提供程序类,它为我的基于 post rest 的 Web 服务创建一个图像。我无法制定请求来测试以下内容,最简单的测试方法是什么? @POST
我一直在 Windows 10 的模拟器中练习 c。后来我改用dev C++ IDE。当我在 C 中使用 FILE 时。创建的文件的名称为 test.txt ,而我给出了其他名称。请帮助解决它。 下面
当我们创建自定义 View 时,我们将 View 文件的所有者设置为自定义类,并使用 initWithFrame 或 initWithCode 对其进行实例化。 当我们创建 customUITable
我正在尝试为函数 * Producer 创建一个线程,但用于创建线程的行显示错误。我为这句话加了星标,但我无法弄清楚它出了什么问题...... #include #include #include
今天在做项目时,遇到了需要创建JavaScript对象的情况。所以Bing了一篇老外写的关于3种创建JavaScript对象的文章,看后跟着打了一遍代码。感觉方法挺好的,在这里与大家分享一下。 &
我正在阅读将查询字符串传递给 Amazon 的 S3 以进行身份验证的文档,但似乎无法理解 StringToSign 的创建和使用方式。我正在寻找一个具体示例来说明 (1) 如何构造 String
前言:我对 C# 中任务的底层实现不太了解,只了解它们的用法。为我在下面屠宰的任何东西道歉: 对于“我怎样才能开始一项任务但不等待它?”这个问题,我找不到一个好的答案。在 C# 中。更具体地说,即使任
我有一个由一些复杂的表达式生成的 ILookup。假设这是按姓氏查找人。 (在我们简单的世界模型中,姓氏在家庭中是唯一的) ILookup families; 现在我有两个对如何构建感兴趣的查询。 首
我试图创建一个 MSI,其中包含 和 exe。在 WIX 中使用了捆绑选项。这样做时出错。有人可以帮我解决这个问题。下面是代码: 错误 error LGH
在 Yii 中,Create 和 Update 通常使用相同的形式。因此,如果我在创建期间有电子邮件、密码、...other_fields...等字段,但我不想在更新期间专门显示电子邮件和密码字段,但
上周我一直在努力创建一个给定一行和一列的 QModelIndex。 或者,我会满足于在已经存在的 QModelIndex 中更改 row() 的值。 任何帮助,将不胜感激。 编辑: QModelInd
出于某种原因,这不起作用: const char * str_reset_command = "\r\nReset"; const char * str_config_command = "\r\nC
现在,我有以下由 original.df %.% group_by(Category) %.% tally() %.% arrange(desc(n)) 创建的 data.frame。 DF 5),
在今天之前,我使用/etc/vim/vimrc来配置我的vim设置。今天,我想到了创建.vimrc文件。所以,我用 touch .vimrc cat /etc/vim/vimrc > .vimrc 所
我可以创建一个 MKAnnotation,还是只读的?我有坐标,但我发现使用 setCooperative 手动创建 MKAnnotation 并不容易。 想法? 最佳答案 MKAnnotation
在以下代码中,第一个日志语句按预期显示小数,但第二个日志语句记录 NULL。我做错了什么? NSDictionary *entry = [[NSDictionary alloc] initWithOb
我正在使用与此类似的代码动态添加到数组; $arrayF[$f+1][$y][$x+1] = $value+1; 但是我在错误报告中收到了这个: undefined offset :1 问题:尝试创
我是一名优秀的程序员,十分优秀!