shell: refine AirPods opening card
This commit is contained in:
parent
8bc9c9a704
commit
bfd48fcf8f
1 changed files with 138 additions and 53 deletions
|
|
@ -64,8 +64,8 @@ Scope {
|
|||
id: card
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Math.min(parent.width - 32, 368)
|
||||
height: 316
|
||||
width: Math.min(parent.width - 36, 356)
|
||||
height: 292
|
||||
opacity: scope.canShow ? 1 : 0
|
||||
scale: scope.canShow ? 1 : 0.94
|
||||
|
||||
|
|
@ -74,8 +74,8 @@ Scope {
|
|||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 36
|
||||
color: "#e81a1c21"
|
||||
radius: 32
|
||||
color: "#eb15171c"
|
||||
border.width: 1
|
||||
border.color: "#3ffffffF"
|
||||
}
|
||||
|
|
@ -83,16 +83,16 @@ Scope {
|
|||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 1
|
||||
radius: 35
|
||||
radius: 31
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0; color: "#f425282f" }
|
||||
GradientStop { position: 1; color: "#f1101115" }
|
||||
GradientStop { position: 0; color: "#f42b3039" }
|
||||
GradientStop { position: 1; color: "#f10f1014" }
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 25
|
||||
anchors.margins: 23
|
||||
spacing: 0
|
||||
|
||||
RowLayout {
|
||||
|
|
@ -100,7 +100,7 @@ Scope {
|
|||
Text {
|
||||
text: AccessoryPresentation.label
|
||||
color: "#f7f7f8"
|
||||
font.pixelSize: 21
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
Item { Layout.fillWidth: true }
|
||||
|
|
@ -114,8 +114,8 @@ Scope {
|
|||
Item {
|
||||
id: stage
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 178
|
||||
Layout.topMargin: 7
|
||||
Layout.preferredHeight: 157
|
||||
Layout.topMargin: 3
|
||||
|
||||
property real open: 0
|
||||
property int seenGeneration: -1
|
||||
|
|
@ -133,78 +133,163 @@ Scope {
|
|||
|
||||
SequentialAnimation {
|
||||
id: reveal
|
||||
NumberAnimation { target: stage; property: "open"; to: 1; duration: 720; easing.type: Easing.OutCubic }
|
||||
NumberAnimation { target: stage; property: "open"; to: 1; duration: 620; easing.type: Easing.OutQuart }
|
||||
}
|
||||
|
||||
// A quiet pool of light beneath the case makes the
|
||||
// device feel present without importing artwork.
|
||||
// Keep the object light, not illustrated. The pool
|
||||
// gives the white case a place to sit without turning
|
||||
// the card into a product render.
|
||||
Rectangle {
|
||||
width: 238; height: 48; radius: height / 2
|
||||
width: 218; height: 36; radius: height / 2
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: 126
|
||||
color: "#263a8dff"
|
||||
opacity: 0.35 * stage.open
|
||||
scale: 0.72 + 0.28 * stage.open
|
||||
y: 115
|
||||
color: "#2c70e8"
|
||||
opacity: 0.20 * stage.open
|
||||
scale: 0.76 + 0.24 * stage.open
|
||||
Behavior on opacity { NumberAnimation { duration: 420 } }
|
||||
}
|
||||
|
||||
Item {
|
||||
id: caseArt
|
||||
width: 206; height: 154
|
||||
width: 190; height: 146
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
|
||||
// Buds rise after the lid clears them.
|
||||
// The old 3-D lid was a flat white slab in a real
|
||||
// layer surface. This is deliberately a clear 2-D
|
||||
// silhouette: lid lifts on its hinge, buds clear
|
||||
// the cavity, then the front of the case settles.
|
||||
Item {
|
||||
id: leftBud
|
||||
x: 39; y: 47 - 20 * stage.open
|
||||
opacity: Math.max(0, (stage.open - 0.22) / 0.78)
|
||||
scale: 0.80 + 0.20 * stage.open
|
||||
Rectangle { width: 39; height: 66; radius: 19; color: "#f4f6f8" }
|
||||
Rectangle { width: 14; height: 43; radius: 7; color: "#f4f6f8"; anchors.horizontalCenter: parent.horizontalCenter; anchors.top: parent.top; anchors.topMargin: 45 }
|
||||
Rectangle { width: 12; height: 4; radius: 2; color: "#c9d0d8"; anchors.horizontalCenter: parent.horizontalCenter; anchors.top: parent.top; anchors.topMargin: 54 }
|
||||
z: 2
|
||||
width: 31; height: 89
|
||||
x: 34; y: 39 - 16 * stage.open
|
||||
opacity: Math.max(0, (stage.open - 0.12) / 0.88)
|
||||
scale: 0.84 + 0.16 * stage.open
|
||||
rotation: -5 * stage.open
|
||||
transformOrigin: Item.Bottom
|
||||
|
||||
Rectangle {
|
||||
width: 31; height: 43; radius: 16
|
||||
color: "#f7f9fb"
|
||||
border.width: 1; border.color: "#ffffff"
|
||||
}
|
||||
Rectangle {
|
||||
width: 11; height: 47; radius: 6
|
||||
x: 10; y: 31
|
||||
color: "#f7f9fb"
|
||||
}
|
||||
Rectangle {
|
||||
width: 7; height: 3; radius: 2
|
||||
x: 12; y: 55
|
||||
color: "#bfc8d1"
|
||||
}
|
||||
Rectangle {
|
||||
width: 6; height: 6; radius: 3
|
||||
x: 6; y: 17
|
||||
color: "#d1d8e0"
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: rightBud
|
||||
x: 128; y: 47 - 20 * stage.open
|
||||
opacity: Math.max(0, (stage.open - 0.22) / 0.78)
|
||||
scale: 0.80 + 0.20 * stage.open
|
||||
Rectangle { width: 39; height: 66; radius: 19; color: "#f4f6f8" }
|
||||
Rectangle { width: 14; height: 43; radius: 7; color: "#f4f6f8"; anchors.horizontalCenter: parent.horizontalCenter; anchors.top: parent.top; anchors.topMargin: 45 }
|
||||
Rectangle { width: 12; height: 4; radius: 2; color: "#c9d0d8"; anchors.horizontalCenter: parent.horizontalCenter; anchors.top: parent.top; anchors.topMargin: 54 }
|
||||
z: 2
|
||||
width: 31; height: 89
|
||||
x: 125; y: 39 - 16 * stage.open
|
||||
opacity: Math.max(0, (stage.open - 0.12) / 0.88)
|
||||
scale: 0.84 + 0.16 * stage.open
|
||||
rotation: 5 * stage.open
|
||||
transformOrigin: Item.Bottom
|
||||
|
||||
Rectangle {
|
||||
width: 31; height: 43; radius: 16
|
||||
color: "#f7f9fb"
|
||||
border.width: 1; border.color: "#ffffff"
|
||||
}
|
||||
Rectangle {
|
||||
width: 11; height: 47; radius: 6
|
||||
x: 10; y: 31
|
||||
color: "#f7f9fb"
|
||||
}
|
||||
Rectangle {
|
||||
width: 7; height: 3; radius: 2
|
||||
x: 12; y: 55
|
||||
color: "#bfc8d1"
|
||||
}
|
||||
Rectangle {
|
||||
width: 6; height: 6; radius: 3
|
||||
x: 19; y: 17
|
||||
color: "#d1d8e0"
|
||||
}
|
||||
}
|
||||
|
||||
// Case body. The lid rotates up from its hinge as
|
||||
// the admitted event lands, then waits in that pose.
|
||||
Rectangle {
|
||||
id: caseBody
|
||||
width: 174; height: 94; radius: 43
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
color: "#f2f4f6"
|
||||
z: 4
|
||||
width: 174; height: 68; radius: 34
|
||||
x: 8; y: 78
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0; color: "#ffffff" }
|
||||
GradientStop { position: 1; color: "#e9edf1" }
|
||||
}
|
||||
border.width: 1
|
||||
border.color: "#ffffff"
|
||||
|
||||
// A small, shadowed mouth makes the buds read
|
||||
// as nested in a case rather than pasted on it.
|
||||
Rectangle {
|
||||
width: 150; height: 29; radius: 15
|
||||
x: 12; y: 5
|
||||
color: "#ccd3db"
|
||||
opacity: 0.14 + 0.52 * stage.open
|
||||
}
|
||||
Rectangle {
|
||||
width: 146; height: 1; radius: 1
|
||||
x: 14; y: 28
|
||||
color: "#c8d0d8"
|
||||
opacity: 0.55
|
||||
}
|
||||
Rectangle {
|
||||
width: 7; height: 7; radius: 4
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
y: 42
|
||||
color: "#58d979"
|
||||
opacity: 0.45 + 0.55 * stage.open
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: lid
|
||||
width: 174; height: 69; radius: 40
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
y: 58
|
||||
color: "#fafbfd"
|
||||
// It is the rear half of an open case: behind
|
||||
// the buds, not a white bar painted across
|
||||
// their faces.
|
||||
z: 1
|
||||
width: 166; height: 58 - 17 * stage.open; radius: height / 2
|
||||
// Closed, the lid meets the front shell. As it
|
||||
// opens, the hinge rises just enough to leave
|
||||
// the buds a visible throat of air.
|
||||
x: 12; y: 78 - 8 * stage.open - height
|
||||
rotation: -4 * stage.open
|
||||
transformOrigin: Item.Bottom
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0; color: "#ffffff" }
|
||||
GradientStop { position: 1; color: "#edf1f5" }
|
||||
}
|
||||
border.width: 1
|
||||
border.color: "#ffffff"
|
||||
transform: Rotation {
|
||||
origin.x: lid.width / 2
|
||||
origin.y: lid.height
|
||||
axis.x: 1; axis.y: 0; axis.z: 0
|
||||
angle: -73 * stage.open
|
||||
Rectangle {
|
||||
width: 126; height: 1; radius: 1
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 2
|
||||
color: "#d8dee5"
|
||||
opacity: 0.62
|
||||
}
|
||||
Rectangle {
|
||||
width: 136; height: 13; radius: 7
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 6
|
||||
color: "#dbe1e7"
|
||||
opacity: 0.50
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -212,8 +297,8 @@ Scope {
|
|||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
spacing: 10
|
||||
Layout.topMargin: 7
|
||||
spacing: 8
|
||||
ChargePill { Layout.fillWidth: true; label: "Left"; level: AccessoryPresentation.leftCharge }
|
||||
ChargePill { Layout.fillWidth: true; label: "Case"; level: AccessoryPresentation.caseCharge }
|
||||
ChargePill { Layout.fillWidth: true; label: "Right"; level: AccessoryPresentation.rightCharge }
|
||||
|
|
@ -226,8 +311,8 @@ Scope {
|
|||
component ChargePill: Rectangle {
|
||||
required property string label
|
||||
required property int level
|
||||
implicitHeight: 45
|
||||
radius: 15
|
||||
implicitHeight: 42
|
||||
radius: 14
|
||||
color: "#1bffffff"
|
||||
border.width: 1
|
||||
border.color: "#24ffffff"
|
||||
|
|
|
|||
Loading…
Reference in a new issue