// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: MIT global Utils { public pure function MapRange(value: length, inMin: length, inMax: length, outMin: length, outMax: length) -> length { return clamp(outMin, (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin, outMax); } } component SunMoonThumb { in property thumb-position: 50px; Rectangle { width: 200px; height: 100px; border-radius: self.height / 2; clip: true; Rectangle { width: 0px; height: 0px; x: root.thumb-position; Rectangle { width: 260px; height: self.width; background: white; border-radius: self.width / 2; opacity: 0.05; } Rectangle { width: 200px; height: self.width; background: white; border-radius: self.width / 2; opacity: 0.05; } Rectangle { width: 140px; height: self.width; background: white; border-radius: self.width / 2; opacity: 0.05; } clipper :=Rectangle { width: 85px; height: self.width; border-radius: self.width / 2; clip: true; sun := Rectangle { width: 85px; height: self.width; background: @radial-gradient(circle,#ffce08 0%, #fdd224 80%, #fce37f 100%); border-radius: self.width / 2; } moon := Rectangle { x: Utils.MapRange(root.thumb-position, 50px, 100px, 85px, 0px); width: 85px; height: self.width; background: @radial-gradient(circle,#bcbcbc 0%, #e7e7e7 80%, #ffffff 100%); border-radius: self.width / 2; } } } } } enum Theme { day, night } export component SunMoonSwitch { property theme: Theme.night; width: 200px; height: 100px; frameBacker := Rectangle { width: parent.width; height: parent.height; background: #1e2232; border-radius: self.height / 2; } Rectangle { width: parent.width; height: parent.height; clip: true; border-radius: self.height / 2; clouds-background :=Image { x: 14px; y: -6px; width: 202px; source: @image-url("images/clouds-background.png"); } clouds-foreground := Image { x: 30px; y: 5px; width: 202px; source: @image-url("images/clouds-front.png"); } stars := Image { x: 15px; y: 15px; width: 80px; source: @image-url("images/stars.png"); } } Image { x: -1px; width: 202px; source: @image-url("images/shadow-frame.png"); } thumb := SunMoonThumb { } TouchArea { clicked => { if root.theme == Theme.day { root.theme = Theme.night; } else { root.theme = Theme.day; } } } states [ nightMode when root.theme == Theme.night: { thumb.thumb-position: root.width - thumb.width - 50px; frameBacker.background: #1e2232; clouds-background.y: 120px; clouds-foreground.y: 120px; in { animate frameBacker.background, stars.y, stars.opacity { easing: ease-out-sine; duration: 200ms; } animate thumb.thumb-position { easing: cubic-bezier(0.61, 0.21, 0.68, 1.22); duration: 300ms; } animate clouds-background.y, clouds-foreground.y { easing: ease-in-sine; duration: 150ms; } } } dayMode when root.theme == Theme.day: { thumb.thumb-position: 50px; frameBacker.background: #3d85ba; stars.y: - 60px; stars.opacity: 0.4; in { animate frameBacker.background, stars.y, stars.opacity { easing: ease-out-sine; duration: 200ms; } animate thumb.thumb-position { easing: cubic-bezier(0.61, 0.21, 0.68, 1.22); duration: 300ms; } animate clouds-background.y { easing: ease-out-sine; duration: 300ms; } animate clouds-foreground.y { easing: cubic-bezier(0.61, 0.21, 0.68, 1.22); duration: 350ms; } } } ] }