技术标签: 时间调度器 TimelineView原理 SwiftUI 自定义时间调度器 与传统动画结合 关键帧动画
TimelineView(.periodic(from: .now, by: 0.5)) {
timeline in
ViewToEvaluatePeriodically()
}
struct Context {
let cadence: Cadence
let date: Date
enum Cadence: Comparable {
case live
case seconds
case minutes
}
}
struct ManyFaces: View {
static let emoji = ["", "", "", "", "", "", "", "", "", "", "", "", ""]
var body: some View {
TimelineView(.periodic(from: .now, by: 0.2)) {
timeline in
HStack(spacing: 120) {
let randomEmoji = ManyFaces.emoji.randomElement() ?? ""
Text(randomEmoji)
.font(.largeTitle)
.scaleEffect(4.0)
SubView()
}
}
}
struct SubView: View {
var body: some View {
let randomEmoji = ManyFaces.emoji.randomElement() ?? ""
Text(randomEmoji)
.font(.largeTitle)
.scaleEffect(4.0)
}
}
}
struct SubView: View {
let date: Date // just by declaring it, the view will now be recomputed apropriately.
var body: some View {
let randomEmoji = ManyFaces.emoji.randomElement() ?? ""
Text(randomEmoji)
.font(.largeTitle)
.scaleEffect(4.0)
}
}
SubView(date: timeline.date)
TimelineView(.periodic(from: .now, by: 1.0)) {
timeline in
Text("\(timeline.date)")
}
struct ExampleView: View {
var body: some View {
TimelineView(.periodic(from: .now, by: 3.0)) {
timeline in
QuipView(date: timeline.date)
}
}
struct QuipView: View {
@StateObject var quips = QuipDatabase()
let date: Date
var body: some View {
Text("_\(quips.sentence)_")
.onChange(of: date) {
_ in
quips.advance()
}
}
}
}
class QuipDatabase: ObservableObject {
static var sentences = [
"There are two types of people, those who can extrapolate from incomplete data",
"After all is said and done, more is said than done.",
"Haikus are easy. But sometimes they don't make sense. Refrigerator.",
"Confidence is the feeling you have before you really understand the problem."
]
@Published var sentence: String = QuipDatabase.sentences[0]
var idx = 0
func advance() {
idx = (idx + 1) % QuipDatabase.sentences.count
sentence = QuipDatabase.sentences[idx]
}
}
struct Metronome: View {
let bpm: Double = 60 // beats per minute
var body: some View {
TimelineView(.periodic(from: .now, by: 60 / bpm)) {
timeline in
MetronomeBack()
.overlay(MetronomePendulum(bpm: bpm, date: timeline.date))
.overlay(MetronomeFront(), alignment: .bottom)
}
}
}
struct MetronomeBack: View {
let c1 = Color(red: 0, green: 0.3, blue: 0.5, opacity: 1)
let c2 = Color(red: 0, green: 0.46, blue: 0.73, opacity: 1)
var body: some View {
let gradient = LinearGradient(colors: [c1, c2],
startPoint: .topLeading,
endPoint: .bottomTrailing)
RoundedTrapezoid(pct: 0.5, cornerSizes: [CGSize(width: 15, height: 15)])
.foregroundStyle(gradient)
.frame(width: 200, height: 350)
}
}
struct MetronomeFront: View {
var body: some View {
RoundedTrapezoid(pct: 0.85, cornerSizes: [.zero, CGSize(width: 10, height: 10)])
.foregroundStyle(Color(red: 0, green: 0.46, blue: 0.73, opacity: 1))
.frame(width: 180, height: 100).padding(10)
}
}
struct RoundedTrapezoid: Shape {
let pct: CGFloat
let cornerSizes: [CGSize]
func path(in rect: CGRect) -> Path {
return Path {
path in
let (cs1, cs2, cs3, cs4) = decodeCornerSize()
// Start of path
let start = CGPoint(x: rect.midX, y: 0)
// width base and top
let wb = rect.size.width
let wt = wb * pct
// angles
let angle: CGFloat = atan(Double(rect.height / ((wb - wt) / 2.0)))
// Control points
let c1 = CGPoint(x: (wb - wt) / 2.0, y: 0)
let c2 = CGPoint(x: c1.x + wt, y: 0)
let c3 = CGPoint(x: wb, y: rect.maxY)
let c4 = CGPoint(x: 0, y: rect.maxY)
// Points a and b
let pa2 = CGPoint(x: c2.x - cs2.width, y: 0)
let pb2 = CGPoint(x: c2.x + CGFloat(cs2.height * tan((.pi/2) - angle)), y: cs2.height)
let pb3 = CGPoint(x: c3.x - cs3.width, y: rect.height)
let pa3 = CGPoint(x: c3.x - (cs3.height != 0 ? CGFloat(tan(angle) / cs3.height) : 0.0), y: rect.height - cs3.height)
let pa4 = CGPoint(x: c4.x + cs4.width, y: rect.height)
let pb4 = CGPoint(x: c4.x + (cs4.height != 0 ? CGFloat(tan(angle) / cs4.height) : 0.0), y: rect.height - cs4.height)
let pb1 = CGPoint(x: c1.x + cs1.width, y: 0)
let pa1 = CGPoint(x: c1.x - CGFloat(cs1.height * tan((.pi/2) - angle)), y: cs1.height)
path.move(to: start)
path.addLine(to: pa2)
path.addQuadCurve(to: pb2, control: c2)
path.addLine(to: pa3)
path.addQuadCurve(to: pb3, control: c3)
path.addLine(to: pa4)
path.addQuadCurve(to: pb4, control: c4)
path.addLine(to: pa1)
path.addQuadCurve(to: pb1, control: c1)
path.closeSubpath()
}
}
func decodeCornerSize() -> (CGSize, CGSize, CGSize, CGSize) {
if cornerSizes.count == 1 {
// If only one corner size is provided, use it for all corners
return (cornerSizes[0], cornerSizes[0], cornerSizes[0], cornerSizes[0])
} else if cornerSizes.count == 2 {
// If only two corner sizes are provided, use one for the two top corners,
// and the other for the two bottom corners
return (cornerSizes[0], cornerSizes[0], cornerSizes[1], cornerSizes[1])
} else if cornerSizes.count == 4 {
// If four corners are provided, use one for each corner
return (cornerSizes[0], cornerSizes[1], cornerSizes[2], cornerSizes[3])
} else {
// In any other case, do not round corners
return (.zero, .zero, .zero, .zero)
}
}
}
struct MetronomePendulum: View {
@State var pendulumOnLeft: Bool = false
@State var bellCounter = 0 // sound bell every 4 beats
let bpm: Double
let date: Date
var body: some View {
Pendulum(angle: pendulumOnLeft ? -30 : 30)
.animation(.easeInOut(duration: 60 / bpm), value: pendulumOnLeft)
.onChange(of: date) {
_ in beat() }
.onAppear {
beat() }
}
func beat() {
pendulumOnLeft.toggle() // triggers the animation
bellCounter = (bellCounter + 1) % 4 // keeps count of beats, to sound bell every 4th
// sound bell or beat?
if bellCounter == 0 {
bellSound?.play()
} else {
beatSound?.play()
}
}
struct Pendulum: View {
let angle: Double
var body: some View {
return Capsule()
.fill(.red)
.frame(width: 10, height: 320)
.overlay(weight)
.rotationEffect(Angle.degrees(angle), anchor: .bottom)
}
var weight: some View {
RoundedRectangle(cornerRadius: 10)
.fill(.orange)
.frame(width: 35, height: 35)
.padding(.bottom, 200)
}
}
}
let bellSound: NSSound? = {
guard let url = Bundle.main.url(forResource: "bell", withExtension: "mp3") else {
return nil }
return NSSound(contentsOf: url, byReference: true)
}()
let beatSound: NSSound? = {
guard let url = Bundle.main.url(forResource: "beat", withExtension: "mp3") else {
return nil }
return NSSound(contentsOf: url, byReference: true)
}()
Timeline(EveryMinuteTimelineSchedule()) {
timeline in
...
}
TimelineView(.everyMinute) {
timeline in
...
}
TimelineView(.animation) {
... }
TimelineView(.animation(minimumInterval: 0.3, paused: false)) {
... }
extension TimelineSchedule where Self == PeriodicTimelineSchedule {
static var everyFiveSeconds: PeriodicTimelineSchedule {
get {
.init(from: .now, by: 5.0) }
}
}
struct ContentView: View {
var body: some View {
TimelineView(.everyFiveSeconds) {
timeline in
...
}
}
}
struct CyclicTimelineSchedule: TimelineSchedule {
let timeOffsets: [TimeInterval]
func entries(from startDate: Date, mode: TimelineScheduleMode) -> Entries {
Entries(last: startDate, offsets: timeOffsets)
}
struct Entries: Sequence, IteratorProtocol {
var last: Date
let offsets: [TimeInterval]
var idx: Int = -1
mutating func next() -> Date? {
idx = (idx + 1) % offsets.count
last = last.addingTimeInterval(offsets[idx])
return last
}
}
}
extension TimelineSchedule where Self == CyclicTimelineSchedule {
static func cyclic(timeOffsets: [TimeInterval]) -> CyclicTimelineSchedule {
.init(timeOffsets: timeOffsets)
}
}
struct BeatingHeart: View {
var body: some View {
TimelineView(.cyclic(timeOffsets: [0.2, 0.2, 0.4])) {
timeline in
Heart(date: timeline.date)
}
}
}
struct Heart: View {
@State private var phase = 0
let scales: [CGFloat] = [1.0, 1.6, 2.0]
let date: Date
var body: some View {
HStack {
Text("️")
.font(.largeTitle)
.scaleEffect(scales[phase])
.animation(.spring(response: 0.10,
dampingFraction: 0.24,
blendDuration: 0.2),
value: phase)
.onChange(of: date) {
_ in
advanceAnimationPhase()
}
.onAppear {
advanceAnimationPhase()
}
}
}
func advanceAnimationPhase() {
phase = (phase + 1) % scales.count
}
}
struct KeyFrame {
let offset: TimeInterval
let rotation: Double
let yScale: Double
let y: CGFloat
let animation: Animation?
}
let keyframes = [
// Initial state, will be used once. Its offset is useless and will be ignored
KeyFrame(offset: 0.0, rotation: 0, yScale: 1.0, y: 0, animation: nil),
// Animation keyframes
KeyFrame(offset: 0.2, rotation: 0, yScale: 0.5, y: 20, animation: .linear(duration: 0.2)),
KeyFrame(offset: 0.4, rotation: 0, yScale: 1.0, y: -20, animation: .linear(duration: 0.4)),
KeyFrame(offset: 0.5, rotation: 360, yScale: 1.0, y: -80, animation: .easeOut(duration: 0.5)),
KeyFrame(offset: 0.4, rotation: 360, yScale: 1.0, y: -20, animation: .easeIn(duration: 0.4)),
KeyFrame(offset: 0.2, rotation: 360, yScale: 0.5, y: 20, animation: .easeOut(duration: 0.2)),
KeyFrame(offset: 0.4, rotation: 360, yScale: 1.0, y: -20, animation: .linear(duration: 0.4)),
KeyFrame(offset: 0.5, rotation: 0, yScale: 1.0, y: -80, animation: .easeOut(duration: 0.5)),
KeyFrame(offset: 0.4, rotation: 0, yScale: 1.0, y: -20, animation: .easeIn(duration: 0.4)),
]
struct JumpingEmoji: View {
// Use all offset, minus the first
let offsets = Array(keyframes.map {
$0.offset }.dropFirst())
var body: some View {
TimelineView(.cyclic(timeOffsets: offsets)) {
timeline in
HappyEmoji(date: timeline.date)
}
}
}
struct HappyEmoji: View {
// current keyframe number
@State var idx: Int = 0
// timeline update
let date: Date
var body: some View {
Text("")
.font(.largeTitle)
.scaleEffect(4.0)
.modifier(Effects(keyframe: keyframes[idx]))
.animation(keyframes[idx].animation, value: idx)
.onChange(of: date) {
_ in advanceKeyFrame() }
.onAppear {
advanceKeyFrame()}
}
func advanceKeyFrame() {
// advance to next keyframe
idx = (idx + 1) % keyframes.count
// skip first frame for animation, which we
// only used as the initial state.
if idx == 0 {
idx = 1 }
}
struct Effects: ViewModifier {
let keyframe: KeyFrame
func body(content: Content) -> some View {
content
.scaleEffect(CGSize(width: 1.0, height: keyframe.yScale))
.rotationEffect(Angle(degrees: keyframe.rotation))
.offset(y: keyframe.y)
}
}
}
Action Tried to Update Multiple Times Per Frame
struct ExampleView: View {
@State private var flag = false
var body: some View {
TimelineView(.periodic(from: .now, by: 2.0)) {
timeline in
Text("Hello")
.foregroundStyle(flag ? .red : .blue)
.onChange(of: timeline.date) {
(date: Date) in
flag.toggle()
}
}
}
}
struct ExampleView: View {
var body: some View {
TimelineView(.periodic(from: .now, by: 1.0)) {
timeline in
SubView(date: timeline.date)
}
}
}
struct SubView: View {
@State private var flag = false
let date: Date
var body: some View {
Text("Hello")
.foregroundStyle(flag ? .red : .blue)
.onChange(of: date) {
(date: Date) in
flag.toggle()
}
}
}
enum KeyFrameAnimation {
case none
case linear
case easeOut
case easeIn
}
struct KeyFrame {
let offset: TimeInterval
let rotation: Double
let yScale: Double
let y: CGFloat
let animationKind: KeyFrameAnimation
var animation: Animation? {
switch animationKind {
case .none: return nil
case .linear: return .linear(duration: offset)
case .easeIn: return .easeIn(duration: offset)
case .easeOut: return .easeOut(duration: offset)
}
}
}
let keyframes = [
// Initial state, will be used once. Its offset is useless and will be ignored
KeyFrame(offset: 0.0, rotation: 0, yScale: 1.0, y: 0, animationKind: .none),
// Animation keyframes
KeyFrame(offset: 0.2, rotation: 0, yScale: 0.5, y: 20, animationKind: .linear),
KeyFrame(offset: 0.4, rotation: 0, yScale: 1.0, y: -20, animationKind: .linear),
KeyFrame(offset: 0.5, rotation: 360, yScale: 1.0, y: -80, animationKind: .easeOut),
KeyFrame(offset: 0.4, rotation: 360, yScale: 1.0, y: -20, animationKind: .easeIn),
KeyFrame(offset: 0.2, rotation: 360, yScale: 0.5, y: 20, animationKind: .easeOut),
KeyFrame(offset: 0.4, rotation: 360, yScale: 1.0, y: -20, animationKind: .linear),
KeyFrame(offset: 0.5, rotation: 0, yScale: 1.0, y: -80, animationKind: .easeOut),
KeyFrame(offset: 0.4, rotation: 0, yScale: 1.0, y: -20, animationKind: .easeIn),
]
import SwiftUI
struct CyclicTimelineSchedule: TimelineSchedule {
let timeOffsets: [TimeInterval]
func entries(from startDate: Date, mode: TimelineScheduleMode) -> Entries {
Entries(last: startDate, offsets: timeOffsets)
}
struct Entries: Sequence, IteratorProtocol {
var last: Date
let offsets: [TimeInterval]
var idx: Int = -1
mutating func next() -> Date? {
idx = (idx + 1) % offsets.count
last = last.addingTimeInterval(offsets[idx])
return last
}
}
}
extension TimelineSchedule where Self == CyclicTimelineSchedule {
static func cyclic(timeOffsets: [TimeInterval]) -> CyclicTimelineSchedule {
.init(timeOffsets: timeOffsets)
}
}
enum KeyFrameAnimation {
case none
case linear
case easeOut
case easeIn
}
struct KeyFrame {
let offset: TimeInterval
let rotation: Double
let yScale: Double
let y: CGFloat
let animationKind: KeyFrameAnimation
var animation: Animation? {
switch animationKind {
case .none: return nil
case .linear: return .linear(duration: offset)
case .easeIn: return .easeIn(duration: offset)
case .easeOut: return .easeOut(duration: offset)
}
}
}
let keyframes = [
// Initial state, will be used once. Its offset is useless and will be ignored
KeyFrame(offset: 0.0, rotation: 0, yScale: 1.0, y: 0, animationKind: .none),
// Animation keyframes
KeyFrame(offset: 0.2, rotation: 0, yScale: 0.5, y: 20, animationKind: .linear),
KeyFrame(offset: 0.4, rotation: 0, yScale: 1.0, y: -20, animationKind: .linear),
KeyFrame(offset: 0.5, rotation: 360, yScale: 1.0, y: -80, animationKind: .easeOut),
KeyFrame(offset: 0.4, rotation: 360, yScale: 1.0, y: -20, animationKind: .easeIn),
KeyFrame(offset: 0.2, rotation: 360, yScale: 0.5, y: 20, animationKind: .easeOut),
KeyFrame(offset: 0.4, rotation: 360, yScale: 1.0, y: -20, animationKind: .linear),
KeyFrame(offset: 0.5, rotation: 0, yScale: 1.0, y: -80, animationKind: .easeOut),
KeyFrame(offset: 0.4, rotation: 0, yScale: 1.0, y: -20, animationKind: .easeIn),
]
struct ManyEmojis: View {
@State var emojiCount = 0
let dates: [Date] = [.now.addingTimeInterval(0.3), .now.addingTimeInterval(0.6), .now.addingTimeInterval(0.9)]
var body: some View {
TimelineView(.explicit(dates)) {
timeline in
HStack(spacing: 80) {
if emojiCount > 0 {
JumpingEmoji(emoji: "")
}
if emojiCount > 1 {
JumpingEmoji(emoji: "")
}
if emojiCount > 2 {
JumpingEmoji(emoji: "")
}
Spacer()
}
.onChange(of: timeline.date) {
(date: Date) in
emojiCount += 1
}
.frame(width: 400)
}
}
}
struct JumpingEmoji: View {
let emoji: String
// Use all offset, minus the first
let offsets = Array(keyframes.map {
$0.offset }.dropFirst())
var body: some View {
TimelineView(.cyclic(timeOffsets: offsets)) {
timeline in
HappyEmoji(emoji: emoji, date: timeline.date)
}
}
}
struct HappyEmoji: View {
let emoji: String
// current keyframe number
@State var idx: Int = 0
// timeline update
let date: Date
var body: some View {
Text(emoji)
.font(.largeTitle)
.scaleEffect(4.0)
.modifier(Effects(keyframe: keyframes[idx]))
.animation(keyframes[idx].animation, value: idx)
.onChange(of: date) {
_ in advanceKeyFrame() }
.onAppear {
advanceKeyFrame()}
}
func advanceKeyFrame() {
// advance to next keyframe
idx = (idx + 1) % keyframes.count
// skip first frame for animation, which we
// only used as the initial state.
if idx == 0 {
idx = 1 }
}
struct Effects: ViewModifier {
let keyframe: KeyFrame
func body(content: Content) -> some View {
content
.scaleEffect(CGSize(width: 1.0, height: keyframe.yScale))
.rotationEffect(Angle(degrees: keyframe.rotation))
.offset(y: keyframe.y)
}
}
}
import SwiftUI
// Sample usage
struct ContentView: View {
var body: some View {
VStack {
GifImage(url: URL(string: "https://media.giphy.com/media/YAlhwn67KT76E/giphy.gif?cid=790b7611b26260b2ad23535a70e343e67443ff80ef623844&rid=giphy.gif&ct=g")!)
.padding(10)
.overlay {
RoundedRectangle(cornerRadius: 8)
.stroke(.green)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
// ObservableObject that holds the data and logic to get all frames in the gif image.
class GifData: ObservableObject {
var loopCount: Int = 0
var width: CGFloat = 0
var height: CGFloat = 0
var capInsets: EdgeInsets?
var resizingMode: Image.ResizingMode
struct ImageFrame {
let image: Image
let delay: TimeInterval
}
var frames: [ImageFrame] = []
init(url: URL, capInsets: EdgeInsets?, resizingMode: Image.ResizingMode) {
self.capInsets = capInsets
self.resizingMode = resizingMode
let label = url.deletingPathExtension().lastPathComponent
Task {
guard let (data, _) = try? await URLSession.shared.data(from: url) else {
return }
guard let source = CGImageSourceCreateWithData(data as CFData, nil) else {
return }
let imageCount = CGImageSourceGetCount(source)
guard let imgProperties = CGImageSourceCopyProperties(source, nil) as? Dictionary<String, Any> else {
return }
guard let gifProperties = imgProperties[kCGImagePropertyGIFDictionary as String] as? Dictionary<String, Any> else {
return }
loopCount = gifProperties[kCGImagePropertyGIFLoopCount as String] as? Int ?? 0
width = gifProperties[kCGImagePropertyGIFCanvasPixelWidth as String] as? CGFloat ?? 0
height = gifProperties[kCGImagePropertyGIFCanvasPixelHeight as String] as? CGFloat ?? 0
let frameInfo = gifProperties[kCGImagePropertyGIFFrameInfoArray as String] as? [Dictionary<String, TimeInterval>] ?? []
for i in 0 ..< min(imageCount, frameInfo.count) {
if let image = CGImageSourceCreateImageAtIndex(source, i, nil) {
var img = Image(image, scale: 1.0, label: Text(label))
if let insets = capInsets {
img = img.resizable(capInsets: insets, resizingMode: resizingMode)
}
frames.append(
ImageFrame(image: img,
delay: frameInfo[i][kCGImagePropertyGIFDelayTime as String] ?? 0.05)
)
}
}
DispatchQueue.main.async {
self.objectWillChange.send() }
}
}
}
// The GifImage view
struct GifImage: View {
@StateObject var gifData: GifData
/// Create an animated Gif Image
/// - Parameters:
/// - url: the url holding the animated gif file
/// - capInsets: if nil, image is not resizable. Otherwise, the capInsets for image resizing (same as the standard image .resizable() modifier).
/// - resizingMode: ignored if capInsets is nil, otherwise, equivalent to the standard image .resizable() modifier parameter)
init(url: URL, capInsets: EdgeInsets? = nil, resizingMode: Image.ResizingMode = .stretch) {
_gifData = StateObject(wrappedValue: GifData(url: url, capInsets: capInsets, resizingMode: resizingMode))
}
var body: some View {
Group {
if gifData.frames.count == 0 {
Color.clear
} else {
VStack {
TimelineView(.cyclic(loopCount: gifData.loopCount, timeOffsets: gifData.frames.map {
$0.delay })) {
timeline in
ImageFrame(gifData: gifData, date: timeline.date)
}
}
}
}
}
struct ImageFrame: View {
@State private var frame = 0
let gifData: GifData
let date: Date
var body: some View {
gifData.frames[frame].image
.onChange(of: date) {
_ in
frame = (frame + 1) % gifData.frames.count
}
}
}
}
// A cyclic TimelineSchedule
struct CyclicTimelineSchedule: TimelineSchedule {
let loopCount: Int // loopCount == 0 means inifinite loops.
let timeOffsets: [TimeInterval]
func entries(from startDate: Date, mode: TimelineScheduleMode) -> Entries {
Entries(loopCount: loopCount, last: startDate, offsets: timeOffsets)
}
struct Entries: Sequence, IteratorProtocol {
let loopCount: Int
var loops = 0
var last: Date
let offsets: [TimeInterval]
var idx: Int = -1
mutating func next() -> Date? {
idx = (idx + 1) % offsets.count
if idx == 0 {
loops += 1 }
if loopCount != 0 && loops >= loopCount {
return nil }
last = last.addingTimeInterval(offsets[idx])
return last
}
}
}
extension TimelineSchedule where Self == CyclicTimelineSchedule {
static func cyclic(loopCount: Int, timeOffsets: [TimeInterval]) -> CyclicTimelineSchedule {
.init(loopCount: loopCount, timeOffsets: timeOffsets)
}
}
文章浏览阅读927次。文章目录8.1检查8.1.1初步检查8.5建立连接路径8.5.1 sort_inner_and_outer生成连接路径时所使用的算法—动态规划和遗传,动态规划推进到join_ search_one_ level遗传算法推进到merge clump,物理优化的部分从这两个函数开始就进入到了建立连接路径的阶段 连接路径指的是物理连接路径,也就是通过这种路径来实现逻辑连接操作建..._path("keys")
文章浏览阅读6.9k次,点赞5次,收藏35次。基于模板匹配的数字识别,将标准的8*16像素的数字0123456789读取,二值化,对每个数字进行等分区域分割,统计每个区域内的黑色像素点的个数,即为特征初值。采用欧式距离的模板匹配法。z//基于模板匹配的数字识别#include#include#include#include #includeusing namespace std; int main()_基于模板匹配的数字电表数字识别
文章浏览阅读7.2k次,点赞11次,收藏74次。Python代码的编写运行方式详解_python安装好后怎么写代码
文章浏览阅读1.2k次。VS Code配置Code runner_vscode无法识别gcc
文章浏览阅读1.5w次,点赞10次,收藏14次。Unity3D中使用mesh collider和box collider的区别踩坑过程记录。设备是HTC的VIVE 和 Unity 5.xCPU: Intel Xeon Silver 4116 * 2GPU: NVIDIA Quadro P6000RAM: 64GB这个问题是在解决项目卡顿问题的同时出现的:最近在用U3D做一个VR项目,需求是要给网格加碰撞体以实现获取手柄射线与..._mesh collider和box collider
文章浏览阅读4.7k次。问题场景问题一:后端项目jar包打包上传运行,终端上正常,终端退出后,项目未能运行。问题二:第二次上传jar包并运行时提示该端口被占用。解决方法问题一:使用nohub命令启动jar包。nohup java -jar 1.0.0.jar &问题二:由于两次使用的同一个端口,先查找到当前端口正在运行的进程的进程号。netstat -lnp|grep 端口号然后用杀掉进程..._centos启动jar包不显示端口占用
文章浏览阅读130次。WSGI协议首先弄清下面几个概念:WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web server如何与web application通信的规范。server和application的规范在PEP 3333中有具体描述。要实现WSGI协议,必须同时实现web server和..._python uwsgi 和pywsgi
文章浏览阅读399次。一,简单介绍KNN算法---就是获取临近点,范围内,哪一种点最多(例如:红点:6,黑点:2,未知点肯定是红点),就是属于最多一方定义样本,拥有四个样本,已知A区两点分别(2,5)和(1,4),B区(8,1)和(9,2),求灰点(4,3)属于哪一区?代码定义实体类/** * 定义数据和数据类型 * @author peng * */ private s..._jf.knn-%; 9 &
文章浏览阅读8.9k次,点赞2次,收藏9次。对于ffmpeg的配置请看我的上篇博客:http://blog.csdn.net/kuaile123/article/details/11367309所用视频为 flv格式的,用的vs2010,电脑为64位,下面的也是64位,别下错了。因为ffmpeg的函数和版本有关系,这里记录下我所用的整合的版本,是昨天下的最新版的,需要请下载http://download.csdn.n_从视频中获取flag
在直接映射缓存中,每个内存地址通过某种映射函数(通常是地址的一部分)映射到一个特定的缓存行。这种结构简单,硬件实现成本较低,但可能会导致较高的缓存冲突(两个内存地址映射到同一缓存行),从而降低缓存效率。在介绍直接映射之前,以停车场停车作为例子,先把结构的特点简单地概括出来,便于读者了解。
持续学习,跟进Objective-C的最新发展和技术。了解Objective-C的基本语法和编程概念。掌握Objective-C的高级特性和常用框架。应用所学知识,完成实际项目。
设R为G的所有生成树的集合,若T为R中边的权值之和最小的生成树,则T称为G的最小生成树(MST)。每次选则一条权值最小的边,使这条边的两头连通(原本已经连通的不选),直到所有结点都连通。,生成树不同,每棵树的权(即树中所有边上的权值之和)也可能不同。1.最小生成树可能有多个,但边的权值之和总是唯一且最小的;每次将代价最小的新顶点纳入生成树,直到所有顶点都纳入为止。数组,找到最小值,将其加入树中,并继续遍历与其相连的边。数组,初始为false,判断结点是否加入树。最低的,且还没加入树的顶点。