mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 03:31:45 +08:00
Revert 5772 revert 5534 css gradients (#5779)
* Revert "Revert "Css gradients" (#5772)" This reverts commit 7edf56197a179b13e1afe4c706aea4a99ac62aca. * chore(): fix LinearGradient circular dependency
This commit is contained in:

committed by
GitHub

parent
11f0d6e98d
commit
9d21a743c4
@ -34,6 +34,11 @@ export function onToggle(args: EventData) {
|
|||||||
target.backgroundImage = target.backgroundImage ? undefined : `~/ui-tests-app/resources/images/test2.png`;
|
target.backgroundImage = target.backgroundImage ? undefined : `~/ui-tests-app/resources/images/test2.png`;
|
||||||
debugConsole.text += `> background-image: ${target.backgroundImage}\n`;
|
debugConsole.text += `> background-image: ${target.backgroundImage}\n`;
|
||||||
}
|
}
|
||||||
|
else if (button.text === "BGGradient") {
|
||||||
|
const gradient = "linear-gradient(to right, purple, red)";
|
||||||
|
target.backgroundImage = typeof target.backgroundImage === "object" ? undefined : gradient;
|
||||||
|
debugConsole.text += `> background-image: ${gradient} \n`;
|
||||||
|
}
|
||||||
|
|
||||||
scrollView.scrollToVerticalOffset(scrollView.scrollableHeight, true);
|
scrollView.scrollToVerticalOffset(scrollView.scrollableHeight, true);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
<StackLayout id="target" row="1" col="1">
|
<StackLayout id="target" row="1" col="1">
|
||||||
<Button text="BGColor" tap="onToggle"/>
|
<Button text="BGColor" tap="onToggle"/>
|
||||||
<Button text="BGImage" tap="onToggle"/>
|
<Button text="BGImage" tap="onToggle"/>
|
||||||
|
<Button text="BGGradient" tap="onToggle"/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout id="right" class="button-container" row="1" col="2">
|
<StackLayout id="right" class="button-container" row="1" col="2">
|
||||||
<Button text="Color" id="borderRightColor" tap="onToggle"/>
|
<Button text="Color" id="borderRightColor" tap="onToggle"/>
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
import * as pages from "tns-core-modules/ui/page";
|
||||||
|
import { EventData } from "tns-core-modules/data/observable";
|
||||||
|
import * as button from "tns-core-modules/ui/button";
|
||||||
|
|
||||||
|
import { GridLayout } from "tns-core-modules/ui/layouts/grid-layout";
|
||||||
|
|
||||||
|
let testIndex = 0;
|
||||||
|
const tests = [
|
||||||
|
{ name: "black-blue only", backgroundImage: "linear-gradient(to bottom, black, blue)"},
|
||||||
|
{ name: "to bottom green-blue", backgroundImage: "linear-gradient(to bottom, green, blue)"},
|
||||||
|
{ name: "to left yellow-blue", backgroundImage: "linear-gradient(to left, yellow, green)"},
|
||||||
|
{ name: "to right yellow-blue", backgroundImage: "linear-gradient(to right, yellow, green)"},
|
||||||
|
{ name: "-45deg green-blue", backgroundImage: "linear-gradient(-45deg, green, blue)"},
|
||||||
|
{ name: "45deg green-blue", backgroundImage: "linear-gradient(45deg, green, blue)"},
|
||||||
|
|
||||||
|
{ name: "black-blue-pink only", backgroundImage: "linear-gradient(to bottom, black, blue, pink)"},
|
||||||
|
{ name: "to bottom green-blue-pink", backgroundImage: "linear-gradient(to bottom, green, blue, pink)"},
|
||||||
|
{ name: "to left yellow-blue-pink", backgroundImage: "linear-gradient(to left, yellow, green, pink)"},
|
||||||
|
{ name: "to right yellow-blue-pink", backgroundImage: "linear-gradient(to right, yellow, green, pink)"},
|
||||||
|
{ name: "-45deg green-blue-pink", backgroundImage: "linear-gradient(-45deg, green, blue, pink)"},
|
||||||
|
{ name: "45deg green-blue-pink", backgroundImage: "linear-gradient(45deg, green, blue, pink)"},
|
||||||
|
]
|
||||||
|
|
||||||
|
export function onLoaded(args) {
|
||||||
|
applyNextStyle(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onButtonTap(args) {
|
||||||
|
applyNextStyle(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyNextStyle(args) {
|
||||||
|
let page = <pages.Page>args.object.page;
|
||||||
|
let btn = <button.Button>args.object;
|
||||||
|
let gridElement = <GridLayout>page.getViewById("Container");
|
||||||
|
|
||||||
|
btn.text = tests[testIndex].name;
|
||||||
|
gridElement.backgroundImage = tests[testIndex].backgroundImage;
|
||||||
|
|
||||||
|
testIndex = testIndex < tests.length - 1 ? ++testIndex : 0;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="onLoaded">
|
||||||
|
<GridLayout rows="*, 7*">
|
||||||
|
<Button row="0" text="a1" tap="onButtonTap"/>
|
||||||
|
|
||||||
|
<GridLayout id="Container" fontSize="12" borderColor="black" margin="5" borderWidth="1" row="1"/>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
@ -9,7 +9,9 @@ const tests = [
|
|||||||
{ name: "black hex color only", background: "#000000" },
|
{ name: "black hex color only", background: "#000000" },
|
||||||
{ name: "yellow hex color only", background: "#ffff00" },
|
{ name: "yellow hex color only", background: "#ffff00" },
|
||||||
{ name: "blue color only", background: "blue" },
|
{ name: "blue color only", background: "blue" },
|
||||||
|
|
||||||
{ name: "repeat image only", background: "url(\"~/ui-tests-app/resources/images/icon.png\")" },
|
{ name: "repeat image only", background: "url(\"~/ui-tests-app/resources/images/icon.png\")" },
|
||||||
|
{ name: "linear gradient red-blue only", background: "linear-gradient(to bottom, red, blue)"},
|
||||||
|
|
||||||
{ name: "[straight] image only, no-repeat ", background: "url(\"~/ui-tests-app/resources/images/icon.png\") no-repeat" },
|
{ name: "[straight] image only, no-repeat ", background: "url(\"~/ui-tests-app/resources/images/icon.png\") no-repeat" },
|
||||||
{ name: "[straight] green color, image, no-repeat", background: "green url(\"~/ui-tests-app/resources/images/icon.png\") no-repeat" },
|
{ name: "[straight] green color, image, no-repeat", background: "green url(\"~/ui-tests-app/resources/images/icon.png\") no-repeat" },
|
||||||
@ -18,7 +20,7 @@ const tests = [
|
|||||||
{ name: "[straight] orange hex color, image, no-repeat, position percents", background: "#F9791F url(\"~/ui-tests-app/resources/images/icon.png\") no-repeat 100% 100%" },
|
{ name: "[straight] orange hex color, image, no-repeat, position percents", background: "#F9791F url(\"~/ui-tests-app/resources/images/icon.png\") no-repeat 100% 100%" },
|
||||||
{ name: "[straight] green color, image, repeat-x, position percents", background: "green url(\"~/ui-tests-app/resources/images/icon.png\") repeat-x 100% 100%" },
|
{ name: "[straight] green color, image, repeat-x, position percents", background: "green url(\"~/ui-tests-app/resources/images/icon.png\") repeat-x 100% 100%" },
|
||||||
{ name: "[straight] blue color, image, repeat-x, position", background: "blue url(\"~/ui-tests-app/resources/images/icon.png\") repeat-x 150 150" },
|
{ name: "[straight] blue color, image, repeat-x, position", background: "blue url(\"~/ui-tests-app/resources/images/icon.png\") repeat-x 150 150" },
|
||||||
|
|
||||||
{ name: "[shuffle] no-repeat, image only", background: "no-repeat url(\"~/ui-tests-app/resources/images/icon.png\")" },
|
{ name: "[shuffle] no-repeat, image only", background: "no-repeat url(\"~/ui-tests-app/resources/images/icon.png\")" },
|
||||||
{ name: "[shuffle] no-repeat, green color, image, ", background: "no-repeat green url(\"~/ui-tests-app/resources/images/icon.png\")" },
|
{ name: "[shuffle] no-repeat, green color, image, ", background: "no-repeat green url(\"~/ui-tests-app/resources/images/icon.png\")" },
|
||||||
{ name: "[shuffle] yellow hex color, position pixels, image, no-repeat", background: "#ffff00 200px 200px url(\"~/ui-tests-app/resources/images/icon.png\") no-repeat" },
|
{ name: "[shuffle] yellow hex color, position pixels, image, no-repeat", background: "#ffff00 200px 200px url(\"~/ui-tests-app/resources/images/icon.png\") no-repeat" },
|
||||||
|
77
apps/app/ui-tests-app/css/gradient-border.css
Normal file
77
apps/app/ui-tests-app/css/gradient-border.css
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
StackLayout {
|
||||||
|
width: 80;
|
||||||
|
height: 80;
|
||||||
|
background: linear-gradient(to top, green, blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
#s0 {
|
||||||
|
border-width: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s1 {
|
||||||
|
border-width: 5; border-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s2 {
|
||||||
|
border-width: 5; border-color: red red red green;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s3 {
|
||||||
|
border-width: 5; border-color: red; border-radius: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s4 {
|
||||||
|
border-width: 5; border-color: red; border-radius: 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s5 {
|
||||||
|
border-width: 5 10 15 20; border-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s6 {
|
||||||
|
border-width: 5; border-color: red green blue yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s7 {
|
||||||
|
border-width: 5 10 15 20; border-color: red green blue yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s8 {
|
||||||
|
border-width: 5 10; border-color: red green;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s9 {
|
||||||
|
border-width: 15 10 5; border-color: red green blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s10 {
|
||||||
|
border-width: 5 0; border-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s11 {
|
||||||
|
background-color: magenta;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s12 {
|
||||||
|
border-width: 5 10 15 20; border-color: red green blue yellow; border-radius: 5 10 15 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s13 {
|
||||||
|
border-width: 5 10 15 20; border-color: red green blue yellow; border-radius: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s14 {
|
||||||
|
border-width: 5 10 15 20; border-color: red green blue yellow; background-color: magenta;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s15 {
|
||||||
|
border-width: 5 10 15 20; border-color: red green blue yellow; background-image: url('~/ui-tests-app/resources/images/test2.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
#s16 {
|
||||||
|
border-width: 5; border-color: red; padding: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#s17 {
|
||||||
|
border-width: 5 6 7 8; border-color: red green blue yellow; padding: 5 6 7 8;
|
||||||
|
}
|
22
apps/app/ui-tests-app/css/gradient-border.xml
Normal file
22
apps/app/ui-tests-app/css/gradient-border.xml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<Page>
|
||||||
|
<GridLayout rows="*,*,*,*,*,*" columns="*,*,*">
|
||||||
|
<StackLayout id="s0" row="0" col="0"/>
|
||||||
|
<StackLayout id="s1" row="0" col="1"/>
|
||||||
|
<StackLayout id="s2" row="0" col="2"/>
|
||||||
|
<StackLayout id="s3" row="1" col="0"/>
|
||||||
|
<StackLayout id="s4" row="1" col="1"/>
|
||||||
|
<StackLayout id="s5" row="1" col="2"/>
|
||||||
|
<StackLayout id="s6" row="2" col="0"/>
|
||||||
|
<StackLayout id="s7" row="2" col="1"/>
|
||||||
|
<StackLayout id="s8" row="2" col="2"/>
|
||||||
|
<StackLayout id="s9" row="3" col="0"/>
|
||||||
|
<StackLayout id="s10" row="3" col="1"/>
|
||||||
|
<StackLayout id="s11" row="3" col="2"/>
|
||||||
|
<StackLayout id="s12" row="4" col="0"/>
|
||||||
|
<StackLayout id="s13" row="4" col="1"/>
|
||||||
|
<StackLayout id="s14" row="4" col="2"/>
|
||||||
|
<StackLayout id="s15" row="5" col="0"/>
|
||||||
|
<StackLayout id="s16" row="5" col="1"/>
|
||||||
|
<StackLayout id="s17" row="5" col="2"/>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
@ -30,6 +30,7 @@ export function loadExamples() {
|
|||||||
examples.set("label-border", "css/label-border");
|
examples.set("label-border", "css/label-border");
|
||||||
examples.set("text-view-border", "css/text-view-border");
|
examples.set("text-view-border", "css/text-view-border");
|
||||||
examples.set("image-border", "css/image-border");
|
examples.set("image-border", "css/image-border");
|
||||||
|
examples.set("gradient-border", "css/gradient-border");
|
||||||
examples.set("layouts-border-overlap", "css/layouts-border-overlap");
|
examples.set("layouts-border-overlap", "css/layouts-border-overlap");
|
||||||
examples.set("measure-tests", "css/measure-tests");
|
examples.set("measure-tests", "css/measure-tests");
|
||||||
examples.set("all-uniform-border", "css/all-uniform-border");
|
examples.set("all-uniform-border", "css/all-uniform-border");
|
||||||
@ -41,5 +42,6 @@ export function loadExamples() {
|
|||||||
examples.set("non-uniform-radius", "css/non-uniform-radius");
|
examples.set("non-uniform-radius", "css/non-uniform-radius");
|
||||||
examples.set("missing-background-image", "css/missing-background-image");
|
examples.set("missing-background-image", "css/missing-background-image");
|
||||||
examples.set("background-shorthand", "css/background-shorthand");
|
examples.set("background-shorthand", "css/background-shorthand");
|
||||||
|
examples.set("background-image-linear-gradient", "css/background-image-linear-gradient");
|
||||||
return examples;
|
return examples;
|
||||||
}
|
}
|
@ -21,9 +21,11 @@ import {
|
|||||||
|
|
||||||
import { createViewFromEntry } from "../../builder";
|
import { createViewFromEntry } from "../../builder";
|
||||||
import { StyleScope } from "../../styling/style-scope";
|
import { StyleScope } from "../../styling/style-scope";
|
||||||
|
import { LinearGradient } from "../../styling/linear-gradient";
|
||||||
|
|
||||||
export * from "../../styling/style-properties";
|
export * from "../../styling/style-properties";
|
||||||
export * from "../view-base";
|
export * from "../view-base";
|
||||||
|
export { LinearGradient };
|
||||||
|
|
||||||
import * as am from "../../animation";
|
import * as am from "../../animation";
|
||||||
let animationModule: typeof am;
|
let animationModule: typeof am;
|
||||||
@ -435,10 +437,10 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
|||||||
this.style.backgroundColor = value;
|
this.style.backgroundColor = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get backgroundImage(): string {
|
get backgroundImage(): string | LinearGradient {
|
||||||
return this.style.backgroundImage;
|
return this.style.backgroundImage;
|
||||||
}
|
}
|
||||||
set backgroundImage(value: string) {
|
set backgroundImage(value: string | LinearGradient) {
|
||||||
this.style.backgroundImage = value;
|
this.style.backgroundImage = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
tns-core-modules/ui/core/view/view.d.ts
vendored
4
tns-core-modules/ui/core/view/view.d.ts
vendored
@ -7,9 +7,11 @@ import { ViewBase, Property, EventData, Color } from "../view-base";
|
|||||||
import { Animation, AnimationDefinition, AnimationPromise } from "../../animation";
|
import { Animation, AnimationDefinition, AnimationPromise } from "../../animation";
|
||||||
import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "../../styling/style-properties";
|
import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "../../styling/style-properties";
|
||||||
import { GestureTypes, GestureEventData, GesturesObserver } from "../../gestures";
|
import { GestureTypes, GestureEventData, GesturesObserver } from "../../gestures";
|
||||||
|
import { LinearGradient } from "../../styling/linear-gradient";
|
||||||
|
|
||||||
export * from "../view-base";
|
export * from "../view-base";
|
||||||
export * from "../../styling/style-properties";
|
export * from "../../styling/style-properties";
|
||||||
|
export { LinearGradient };
|
||||||
|
|
||||||
export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator;
|
export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator;
|
||||||
|
|
||||||
@ -219,7 +221,7 @@ export abstract class View extends ViewBase {
|
|||||||
/**
|
/**
|
||||||
* Gets or sets the background image of the view.
|
* Gets or sets the background image of the view.
|
||||||
*/
|
*/
|
||||||
backgroundImage: string;
|
backgroundImage: string | LinearGradient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or sets the minimum width the view may grow to.
|
* Gets or sets the minimum width the view may grow to.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Deifinitions.
|
// Deifinitions.
|
||||||
import { Background as BackgroundDefinition } from "./background";
|
import { Background as BackgroundDefinition } from "./background";
|
||||||
import { BackgroundRepeat } from "../core/view";
|
import { BackgroundRepeat } from "../core/view";
|
||||||
|
import { LinearGradient } from "./linear-gradient";
|
||||||
// Types.
|
// Types.
|
||||||
import { Color } from "../../color";
|
import { Color } from "../../color";
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ export class Background implements BackgroundDefinition {
|
|||||||
public static default = new Background();
|
public static default = new Background();
|
||||||
|
|
||||||
public color: Color;
|
public color: Color;
|
||||||
public image: string;
|
public image: string | LinearGradient;
|
||||||
public repeat: BackgroundRepeat;
|
public repeat: BackgroundRepeat;
|
||||||
public position: string;
|
public position: string;
|
||||||
public size: string;
|
public size: string;
|
||||||
@ -58,7 +58,7 @@ export class Background implements BackgroundDefinition {
|
|||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public withImage(value: string): Background {
|
public withImage(value: string | LinearGradient): Background {
|
||||||
const clone = this.clone();
|
const clone = this.clone();
|
||||||
clone.image = value;
|
clone.image = value;
|
||||||
return clone;
|
return clone;
|
||||||
@ -179,8 +179,15 @@ export class Background implements BackgroundDefinition {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let imagesEqual = false;
|
||||||
|
if (value1 instanceof LinearGradient && value2 instanceof LinearGradient) {
|
||||||
|
imagesEqual = LinearGradient.equals(value1, value2);
|
||||||
|
} else {
|
||||||
|
imagesEqual = value1.image === value2.image;
|
||||||
|
}
|
||||||
|
|
||||||
return Color.equals(value1.color, value2.color)
|
return Color.equals(value1.color, value2.color)
|
||||||
&& value1.image === value2.image
|
&& imagesEqual
|
||||||
&& value1.position === value2.position
|
&& value1.position === value2.position
|
||||||
&& value1.repeat === value2.repeat
|
&& value1.repeat === value2.repeat
|
||||||
&& value1.size === value2.size
|
&& value1.size === value2.size
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { View } from "../core/view";
|
import { View } from "../core/view";
|
||||||
|
import { LinearGradient } from "./linear-gradient";
|
||||||
|
|
||||||
import { isDataURI, isFileOrResourcePath, layout, RESOURCE_PREFIX, FILE_PREFIX } from "../../utils/utils";
|
import { isDataURI, isFileOrResourcePath, layout, RESOURCE_PREFIX, FILE_PREFIX } from "../../utils/utils";
|
||||||
import { parse } from "../../css-value";
|
import { parse } from "../../css-value";
|
||||||
import { path, knownFolders } from "../../file-system";
|
import { path, knownFolders } from "../../file-system";
|
||||||
@ -104,6 +106,38 @@ function fromBase64(source: string): android.graphics.Bitmap {
|
|||||||
return android.graphics.BitmapFactory.decodeByteArray(bytes, 0, bytes.length)
|
return android.graphics.BitmapFactory.decodeByteArray(bytes, 0, bytes.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fromGradient(gradient: LinearGradient): org.nativescript.widgets.LinearGradientDefinition {
|
||||||
|
const colors = Array.create("int", gradient.colorStops.length);
|
||||||
|
const stops = Array.create("float", gradient.colorStops.length);
|
||||||
|
let hasStops = false;
|
||||||
|
gradient.colorStops.forEach((stop, index) => {
|
||||||
|
colors[index] = stop.color.android;
|
||||||
|
if (stop.offset) {
|
||||||
|
stops[index] = stop.offset.value;
|
||||||
|
hasStops = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const alpha = gradient.angle / (Math.PI * 2);
|
||||||
|
const startX = Math.pow(
|
||||||
|
Math.sin(Math.PI * (alpha + 0.75)),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
const startY = Math.pow(
|
||||||
|
Math.sin(Math.PI * (alpha + 0.5)),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
const endX = Math.pow(
|
||||||
|
Math.sin(Math.PI * (alpha + 0.25)),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
const endY = Math.pow(
|
||||||
|
Math.sin(Math.PI * alpha),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
return new org.nativescript.widgets.LinearGradientDefinition(startX, startY, endX, endY, colors, hasStops ? stops : null);
|
||||||
|
}
|
||||||
|
|
||||||
const pattern: RegExp = /url\(('|")(.*?)\1\)/;
|
const pattern: RegExp = /url\(('|")(.*?)\1\)/;
|
||||||
function refreshBorderDrawable(this: void, view: View, borderDrawable: org.nativescript.widgets.BorderDrawable) {
|
function refreshBorderDrawable(this: void, view: View, borderDrawable: org.nativescript.widgets.BorderDrawable) {
|
||||||
const nativeView = <android.view.View>view.nativeViewProtected;
|
const nativeView = <android.view.View>view.nativeViewProtected;
|
||||||
@ -115,8 +149,9 @@ function refreshBorderDrawable(this: void, view: View, borderDrawable: org.nativ
|
|||||||
const backgroundSizeParsedCSSValues = createNativeCSSValueArray(background.size);
|
const backgroundSizeParsedCSSValues = createNativeCSSValueArray(background.size);
|
||||||
const blackColor = -16777216; //android.graphics.Color.BLACK;
|
const blackColor = -16777216; //android.graphics.Color.BLACK;
|
||||||
|
|
||||||
let imageUri = background.image;
|
let imageUri: string;
|
||||||
if (imageUri) {
|
if (background.image && typeof background.image === "string") {
|
||||||
|
imageUri = background.image;
|
||||||
const match = imageUri.match(pattern);
|
const match = imageUri.match(pattern);
|
||||||
if (match && match[2]) {
|
if (match && match[2]) {
|
||||||
imageUri = match[2];
|
imageUri = match[2];
|
||||||
@ -141,6 +176,11 @@ function refreshBorderDrawable(this: void, view: View, borderDrawable: org.nativ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let gradient: org.nativescript.widgets.LinearGradientDefinition = null;
|
||||||
|
if (background.image && background.image instanceof LinearGradient) {
|
||||||
|
gradient = fromGradient(background.image);
|
||||||
|
}
|
||||||
|
|
||||||
borderDrawable.refresh(
|
borderDrawable.refresh(
|
||||||
background.borderTopColor ? background.borderTopColor.android : blackColor,
|
background.borderTopColor ? background.borderTopColor.android : blackColor,
|
||||||
background.borderRightColor ? background.borderRightColor.android : blackColor,
|
background.borderRightColor ? background.borderRightColor.android : blackColor,
|
||||||
@ -162,6 +202,7 @@ function refreshBorderDrawable(this: void, view: View, borderDrawable: org.nativ
|
|||||||
background.color ? background.color.android : 0,
|
background.color ? background.color.android : 0,
|
||||||
imageUri,
|
imageUri,
|
||||||
bitmap,
|
bitmap,
|
||||||
|
gradient,
|
||||||
context,
|
context,
|
||||||
background.repeat,
|
background.repeat,
|
||||||
background.position,
|
background.position,
|
||||||
|
6
tns-core-modules/ui/styling/background.d.ts
vendored
6
tns-core-modules/ui/styling/background.d.ts
vendored
@ -3,12 +3,12 @@
|
|||||||
*/ /** */
|
*/ /** */
|
||||||
|
|
||||||
import { Color } from "../../color";
|
import { Color } from "../../color";
|
||||||
import { View, BackgroundRepeat } from "../core/view";
|
import { View, BackgroundRepeat, LinearGradient } from "../core/view";
|
||||||
|
|
||||||
export class Background {
|
export class Background {
|
||||||
public static default: Background;
|
public static default: Background;
|
||||||
public color: Color;
|
public color: Color;
|
||||||
public image: string;
|
public image: string | LinearGradient;
|
||||||
public repeat: BackgroundRepeat;
|
public repeat: BackgroundRepeat;
|
||||||
public position: string;
|
public position: string;
|
||||||
public size: string;
|
public size: string;
|
||||||
@ -27,7 +27,7 @@ export class Background {
|
|||||||
public clipPath: string;
|
public clipPath: string;
|
||||||
|
|
||||||
public withColor(value: Color): Background;
|
public withColor(value: Color): Background;
|
||||||
public withImage(value: string): Background;
|
public withImage(value: string | LinearGradient): Background;
|
||||||
public withRepeat(value: BackgroundRepeat): Background;
|
public withRepeat(value: BackgroundRepeat): Background;
|
||||||
public withPosition(value: string): Background;
|
public withPosition(value: string): Background;
|
||||||
public withSize(value: string): Background;
|
public withSize(value: string): Background;
|
||||||
|
@ -2,6 +2,7 @@ import { ScrollEventData } from "../scroll-view";
|
|||||||
|
|
||||||
import { Background as BackgroundDefinition } from "./background";
|
import { Background as BackgroundDefinition } from "./background";
|
||||||
import { View, Point } from "../core/view";
|
import { View, Point } from "../core/view";
|
||||||
|
import { LinearGradient } from "./linear-gradient";
|
||||||
import { Color } from "../../color";
|
import { Color } from "../../color";
|
||||||
import { ios as utilsIos, isDataURI, isFileOrResourcePath, layout } from "../../utils/utils";
|
import { ios as utilsIos, isDataURI, isFileOrResourcePath, layout } from "../../utils/utils";
|
||||||
import { fromFileOrResource, fromBase64, fromUrl } from "../../image-source";
|
import { fromFileOrResource, fromBase64, fromUrl } from "../../image-source";
|
||||||
@ -21,6 +22,8 @@ interface NativeView extends UIView {
|
|||||||
rightBorderLayer: CALayer;
|
rightBorderLayer: CALayer;
|
||||||
bottomBorderLayer: CALayer;
|
bottomBorderLayer: CALayer;
|
||||||
leftBorderLayer: CALayer;
|
leftBorderLayer: CALayer;
|
||||||
|
|
||||||
|
gradientLayer: CAGradientLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Rect {
|
interface Rect {
|
||||||
@ -43,6 +46,11 @@ export module ios {
|
|||||||
clearNonUniformBorders(nativeView);
|
clearNonUniformBorders(nativeView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearGradient(nativeView);
|
||||||
|
if (background.image instanceof LinearGradient) {
|
||||||
|
drawGradient(nativeView, background.image);
|
||||||
|
}
|
||||||
|
|
||||||
const hasNonUniformBorderWidths = background.hasBorderWidth() && !background.hasUniformBorder();
|
const hasNonUniformBorderWidths = background.hasBorderWidth() && !background.hasUniformBorder();
|
||||||
const hasNonUniformBorderRadiuses = background.hasBorderRadius() && !background.hasUniformBorderRadius();
|
const hasNonUniformBorderRadiuses = background.hasBorderRadius() && !background.hasUniformBorderRadius();
|
||||||
if (background.hasUniformBorderColor() && (hasNonUniformBorderWidths || hasNonUniformBorderRadiuses)) {
|
if (background.hasUniformBorderColor() && (hasNonUniformBorderWidths || hasNonUniformBorderRadiuses)) {
|
||||||
@ -67,7 +75,7 @@ export module ios {
|
|||||||
drawClipPath(nativeView, background);
|
drawClipPath(nativeView, background);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!background.image) {
|
if (!background.image || background.image instanceof LinearGradient) {
|
||||||
const uiColor = background.color ? background.color.ios : undefined;
|
const uiColor = background.color ? background.color.ios : undefined;
|
||||||
callback(uiColor);
|
callback(uiColor);
|
||||||
} else {
|
} else {
|
||||||
@ -151,7 +159,7 @@ function setUIColorFromImage(view: View, nativeView: UIView, callback: (uiColor:
|
|||||||
|
|
||||||
const style = view.style;
|
const style = view.style;
|
||||||
const background = style.backgroundInternal;
|
const background = style.backgroundInternal;
|
||||||
let imageUri = background.image;
|
let imageUri = background.image as string;
|
||||||
if (imageUri) {
|
if (imageUri) {
|
||||||
const match = imageUri.match(pattern);
|
const match = imageUri.match(pattern);
|
||||||
if (match && match[2]) {
|
if (match && match[2]) {
|
||||||
@ -663,6 +671,60 @@ function drawNoRadiusNonUniformBorders(nativeView: NativeView, background: Backg
|
|||||||
nativeView.hasNonUniformBorder = hasNonUniformBorder;
|
nativeView.hasNonUniformBorder = hasNonUniformBorder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function drawGradient(nativeView: NativeView, gradient: LinearGradient) {
|
||||||
|
|
||||||
|
const gradientLayer = CAGradientLayer.layer();
|
||||||
|
gradientLayer.frame = nativeView.bounds;
|
||||||
|
nativeView.gradientLayer = gradientLayer;
|
||||||
|
|
||||||
|
const iosColors = NSMutableArray.alloc().initWithCapacity(gradient.colorStops.length);
|
||||||
|
const iosStops = NSMutableArray.alloc<number>().initWithCapacity(gradient.colorStops.length);
|
||||||
|
let hasStops = false;
|
||||||
|
|
||||||
|
gradient.colorStops.forEach(stop => {
|
||||||
|
iosColors.addObject(stop.color.ios.CGColor);
|
||||||
|
if (stop.offset) {
|
||||||
|
iosStops.addObject(stop.offset.value);
|
||||||
|
hasStops = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
gradientLayer.colors = iosColors;
|
||||||
|
|
||||||
|
if (hasStops) {
|
||||||
|
gradientLayer.locations = iosStops;
|
||||||
|
}
|
||||||
|
|
||||||
|
const alpha = gradient.angle / (Math.PI * 2);
|
||||||
|
const startX = Math.pow(
|
||||||
|
Math.sin(Math.PI * (alpha + 0.75)),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
const startY = Math.pow(
|
||||||
|
Math.sin(Math.PI * (alpha + 0.5)),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
const endX = Math.pow(
|
||||||
|
Math.sin(Math.PI * (alpha + 0.25)),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
const endY = Math.pow(
|
||||||
|
Math.sin(Math.PI * alpha),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
gradientLayer.startPoint = {x: startX, y: startY};
|
||||||
|
gradientLayer.endPoint = {x: endX, y: endY};
|
||||||
|
|
||||||
|
nativeView.layer.insertSublayerAtIndex(gradientLayer, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearGradient(nativeView: NativeView): void {
|
||||||
|
if (nativeView.gradientLayer) {
|
||||||
|
nativeView.gradientLayer.removeFromSuperlayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function drawClipPath(nativeView: UIView, background: BackgroundDefinition) {
|
function drawClipPath(nativeView: UIView, background: BackgroundDefinition) {
|
||||||
const layer = nativeView.layer;
|
const layer = nativeView.layer;
|
||||||
const layerBounds = layer.bounds;
|
const layerBounds = layer.bounds;
|
||||||
|
64
tns-core-modules/ui/styling/linear-gradient.ts
Normal file
64
tns-core-modules/ui/styling/linear-gradient.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { LengthPercentUnit } from "./style-properties";
|
||||||
|
import * as parser from "../../css/parser";
|
||||||
|
import { Color } from "../../color";
|
||||||
|
|
||||||
|
export class LinearGradient {
|
||||||
|
public angle: number;
|
||||||
|
public colorStops: ColorStop[];
|
||||||
|
|
||||||
|
static parse(value: parser.LinearGradient): LinearGradient {
|
||||||
|
const result = new LinearGradient();
|
||||||
|
result.angle = value.angle;
|
||||||
|
result.colorStops = value.colors.map(color => {
|
||||||
|
const offset = color.offset || null;
|
||||||
|
let offsetUnit: LengthPercentUnit;
|
||||||
|
|
||||||
|
if (offset && offset.unit === "%") {
|
||||||
|
offsetUnit = {
|
||||||
|
unit: "%",
|
||||||
|
value: offset.value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
color: new Color(color.argb),
|
||||||
|
offset: offsetUnit
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static equals(first: LinearGradient, second: LinearGradient): boolean {
|
||||||
|
if (!first && !second) {
|
||||||
|
return true;
|
||||||
|
} else if (!first || !second) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first.angle !== second.angle) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first.colorStops.length !== second.colorStops.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < first.colorStops.length; i++) {
|
||||||
|
const firstStop = first.colorStops[i];
|
||||||
|
const secondStop = second.colorStops[i];
|
||||||
|
if (firstStop.offset !== secondStop.offset) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!Color.equals(firstStop.color, secondStop.color)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ColorStop {
|
||||||
|
color: Color;
|
||||||
|
offset?: LengthPercentUnit;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
// Types
|
// Types
|
||||||
import { unsetValue, Style,
|
import { unsetValue, Style,
|
||||||
CssProperty, CssAnimationProperty,
|
CssProperty, CssAnimationProperty,
|
||||||
ShorthandProperty, InheritedCssProperty,
|
ShorthandProperty, InheritedCssProperty,
|
||||||
makeValidator, makeParser } from "../core/properties";
|
makeValidator, makeParser } from "../core/properties";
|
||||||
import {
|
import {
|
||||||
@ -27,6 +27,7 @@ import {
|
|||||||
} from "../../matrix";
|
} from "../../matrix";
|
||||||
|
|
||||||
import * as parser from "../../css/parser";
|
import * as parser from "../../css/parser";
|
||||||
|
import { LinearGradient } from "./linear-gradient";
|
||||||
|
|
||||||
export type LengthDipUnit = { readonly unit: "dip", readonly value: dip };
|
export type LengthDipUnit = { readonly unit: "dip", readonly value: dip };
|
||||||
export type LengthPxUnit = { readonly unit: "px", readonly value: px };
|
export type LengthPxUnit = { readonly unit: "px", readonly value: px };
|
||||||
@ -563,10 +564,28 @@ export const backgroundInternalProperty = new CssProperty<Style, Background>({
|
|||||||
backgroundInternalProperty.register(Style);
|
backgroundInternalProperty.register(Style);
|
||||||
|
|
||||||
// const pattern: RegExp = /url\(('|")(.*?)\1\)/;
|
// const pattern: RegExp = /url\(('|")(.*?)\1\)/;
|
||||||
export const backgroundImageProperty = new CssProperty<Style, string>({
|
export const backgroundImageProperty = new CssProperty<Style, string | LinearGradient>({
|
||||||
name: "backgroundImage", cssName: "background-image", valueChanged: (target, oldValue, newValue) => {
|
name: "backgroundImage", cssName: "background-image", valueChanged: (target, oldValue, newValue) => {
|
||||||
const background = target.backgroundInternal.withImage(newValue);
|
const background = target.backgroundInternal.withImage(newValue);
|
||||||
target.backgroundInternal = background;
|
target.backgroundInternal = background;
|
||||||
|
},
|
||||||
|
equalityComparer: (value1, value2) => {
|
||||||
|
if (value1 instanceof LinearGradient && value2 instanceof LinearGradient) {
|
||||||
|
return LinearGradient.equals(value1, value2)
|
||||||
|
} else {
|
||||||
|
return value1 === value2;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
valueConverter: (value: any) => {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
const parsed = parser.parseBackground(value);
|
||||||
|
if (parsed) {
|
||||||
|
const background = parsed.value;
|
||||||
|
value = (typeof background.image === "object") ? LinearGradient.parse(background.image) : value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
backgroundImageProperty.register(Style);
|
backgroundImageProperty.register(Style);
|
||||||
@ -618,7 +637,14 @@ function convertToBackgrounds(this: void, value: string): [CssProperty<any, any>
|
|||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
const backgrounds = parser.parseBackground(value).value;
|
const backgrounds = parser.parseBackground(value).value;
|
||||||
const backgroundColor = backgrounds.color ? new Color(backgrounds.color) : unsetValue;
|
const backgroundColor = backgrounds.color ? new Color(backgrounds.color) : unsetValue;
|
||||||
const backgroundImage = backgrounds.image || unsetValue;
|
|
||||||
|
let backgroundImage: string | LinearGradient;
|
||||||
|
if (typeof backgrounds.image === "object" && backgrounds.image) {
|
||||||
|
backgroundImage = LinearGradient.parse(backgrounds.image);
|
||||||
|
} else {
|
||||||
|
backgroundImage = backgrounds.image || unsetValue;
|
||||||
|
}
|
||||||
|
|
||||||
const backgroundRepeat = backgrounds.repeat || unsetValue;
|
const backgroundRepeat = backgrounds.repeat || unsetValue;
|
||||||
const backgroundPosition = backgrounds.position ? backgrounds.position.text : unsetValue;
|
const backgroundPosition = backgrounds.position ? backgrounds.position.text : unsetValue;
|
||||||
|
|
||||||
|
3
tns-core-modules/ui/styling/style/style.d.ts
vendored
3
tns-core-modules/ui/styling/style/style.d.ts
vendored
@ -11,6 +11,7 @@ import {
|
|||||||
FlexDirection, FlexWrap, JustifyContent, AlignItems, AlignContent,
|
FlexDirection, FlexWrap, JustifyContent, AlignItems, AlignContent,
|
||||||
Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf
|
Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf
|
||||||
} from "../../layouts/flexbox-layout";
|
} from "../../layouts/flexbox-layout";
|
||||||
|
import { LinearGradient } from "../linear-gradient";
|
||||||
|
|
||||||
export interface Thickness {
|
export interface Thickness {
|
||||||
left: number;
|
left: number;
|
||||||
@ -64,7 +65,7 @@ export class Style extends Observable {
|
|||||||
|
|
||||||
public background: string;
|
public background: string;
|
||||||
public backgroundColor: Color;
|
public backgroundColor: Color;
|
||||||
public backgroundImage: string;
|
public backgroundImage: string | LinearGradient;
|
||||||
public backgroundRepeat: BackgroundRepeat;
|
public backgroundRepeat: BackgroundRepeat;
|
||||||
public backgroundSize: string;
|
public backgroundSize: string;
|
||||||
public backgroundPosition: string;
|
public backgroundPosition: string;
|
||||||
|
@ -2,7 +2,8 @@ import { Style as StyleDefinition } from ".";
|
|||||||
import { Color } from "../../../color";
|
import { Color } from "../../../color";
|
||||||
import { Font, FontStyle, FontWeight } from "../font";
|
import { Font, FontStyle, FontWeight } from "../font";
|
||||||
import { Background } from "../background";
|
import { Background } from "../background";
|
||||||
import { Length, PercentLength, ViewBase, BackgroundRepeat, Visibility, HorizontalAlignment, VerticalAlignment, dip } from "../../core/view";
|
import { Length, PercentLength, ViewBase, BackgroundRepeat, Visibility,
|
||||||
|
HorizontalAlignment, VerticalAlignment, dip, LinearGradient } from "../../core/view";
|
||||||
import { Observable } from "../../../data/observable";
|
import { Observable } from "../../../data/observable";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -37,7 +38,7 @@ export class Style extends Observable implements StyleDefinition {
|
|||||||
|
|
||||||
public background: string;
|
public background: string;
|
||||||
public backgroundColor: Color;
|
public backgroundColor: Color;
|
||||||
public backgroundImage: string;
|
public backgroundImage: string | LinearGradient;
|
||||||
public backgroundRepeat: BackgroundRepeat;
|
public backgroundRepeat: BackgroundRepeat;
|
||||||
public backgroundSize: string;
|
public backgroundSize: string;
|
||||||
public backgroundPosition: string;
|
public backgroundPosition: string;
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
backgroundColor: number,
|
backgroundColor: number,
|
||||||
backgroundImage: string,
|
backgroundImage: string,
|
||||||
backgroundBitmap: android.graphics.Bitmap,
|
backgroundBitmap: android.graphics.Bitmap,
|
||||||
|
backgroundGradient: LinearGradientDefinition,
|
||||||
context: android.content.Context,
|
context: android.content.Context,
|
||||||
backgroundRepeat: string,
|
backgroundRepeat: string,
|
||||||
backgroundPosition: string,
|
backgroundPosition: string,
|
||||||
@ -117,6 +118,18 @@
|
|||||||
public toDebugString(): string;
|
public toDebugString(): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class LinearGradientDefinition {
|
||||||
|
constructor(startX: number, endX: number, startY: number,
|
||||||
|
endY: number, colors: number[], stops?: number[]);
|
||||||
|
|
||||||
|
public getStartX(): number;
|
||||||
|
public getStartY(): number;
|
||||||
|
public getEndX(): number;
|
||||||
|
public getEndY(): number;
|
||||||
|
public getColors(): number[];
|
||||||
|
public getStops(): number[];
|
||||||
|
}
|
||||||
|
|
||||||
export class CSSValue {
|
export class CSSValue {
|
||||||
constructor(type: string, str: string, unit: string, value: number);
|
constructor(type: string, str: string, unit: string, value: number);
|
||||||
public getType(): string;
|
public getType(): string;
|
||||||
|
Reference in New Issue
Block a user