diff --git a/components/core/JsInterop/JSInteropConstants.cs b/components/core/JsInterop/JSInteropConstants.cs index d39c1f2f7e..6c646768cb 100644 --- a/components/core/JsInterop/JSInteropConstants.cs +++ b/components/core/JsInterop/JSInteropConstants.cs @@ -100,6 +100,7 @@ public static class JSInteropConstants public static string DisposeObj => $"{FUNC_PREFIX}state.disposeObj"; public static string Log => $"{FUNC_PREFIX}log"; + public static string GenerateColor => $"{FUNC_PREFIX}generateColor"; public static class DomInfoHelper { diff --git a/components/core/JsInterop/interop.ts b/components/core/JsInterop/interop.ts index cc2ed59e70..033cc76201 100644 --- a/components/core/JsInterop/interop.ts +++ b/components/core/JsInterop/interop.ts @@ -14,6 +14,8 @@ export { } from './modules/components/export' export { enableDraggable, disableDraggable, resetModalPosition } from "./modules/dom/dragHelper"; +export { generate as generateColor } from "@ant-design/colors"; + export function log(text) { console.log(text); } diff --git a/components/core/JsInterop/modules/components/iconHelper.ts b/components/core/JsInterop/modules/components/iconHelper.ts index 4279801767..b714c615aa 100644 --- a/components/core/JsInterop/modules/components/iconHelper.ts +++ b/components/core/JsInterop/modules/components/iconHelper.ts @@ -3,9 +3,9 @@ if (document.querySelector(`[data-namespace="${scriptUrl}"]`)) { return; } - const script = document.createElement('script'); - script.setAttribute('src', scriptUrl); - script.setAttribute('data-namespace', scriptUrl); + const script = document.createElement("script"); + script.setAttribute("src", scriptUrl); + script.setAttribute("data-namespace", scriptUrl); document.body.appendChild(script); } -} \ No newline at end of file +} diff --git a/components/icon/Icon.razor b/components/icon/Icon.razor index d86fc197b8..a169df76b8 100644 --- a/components/icon/Icon.razor +++ b/components/icon/Icon.razor @@ -1,7 +1,7 @@ @namespace AntDesign @inherits AntDomComponentBase - + @if (Component == null) { @((MarkupString) _svgImg) diff --git a/components/icon/Icon.razor.cs b/components/icon/Icon.razor.cs index 0dce0c4263..67ec8aa16b 100644 --- a/components/icon/Icon.razor.cs +++ b/components/icon/Icon.razor.cs @@ -1,4 +1,6 @@ -using System.Threading.Tasks; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; @@ -7,8 +9,8 @@ namespace AntDesign public partial class Icon : AntDomComponentBase { [Parameter] - public string Alt {get; set;} - + public string Alt { get; set; } + [Parameter] public bool Spin { get; set; } @@ -25,7 +27,21 @@ public partial class Icon : AntDomComponentBase public string Theme { get; set; } = IconThemeType.Outline; [Parameter] - public string TwotoneColor { get; set; } + public string TwotoneColor + { + get => _twotoneColor; + set + { + if (_twotoneColor != value) + { + _twotoneColor = value; + _twotoneColorChanged = true; + } + } + } + + [Parameter] + public bool AvoidPrerendering { get; set; } [Parameter] public string IconFont { get; set; } @@ -51,20 +67,17 @@ public partial class Icon : AntDomComponentBase [Parameter] public EventCallback OnClick { get; set; } - [Inject] - public IconService IconService { get; set; } - [Parameter] public RenderFragment Component { get; set; } - protected string _svgImg; + [Inject] + public IconService IconService { get; set; } - protected override void Dispose(bool disposing) - { - Button?.Icons.Remove(this); + protected string _svgImg; + private string _twotoneColor = "#1890ff"; + private bool _twotoneColorChanged = false; - base.Dispose(disposing); - } + private Dictionary _attributes = new(); protected override async Task OnInitializedAsync() { @@ -80,37 +93,50 @@ protected override async Task OnInitializedAsync() ClassMapper.Add($"anticon") .GetIf(() => $"anticon-{Type}", () => !string.IsNullOrWhiteSpace(Type)); + if (OnClick.HasDelegate) + { + _attributes.Add("onclick", (Delegate)HandleOnClick); + } + await base.OnInitializedAsync(); } - protected override async Task OnParametersSetAsync() + protected override async Task OnAfterRenderAsync(bool firstRender) { - await SetupSvgImg(); - await base.OnParametersSetAsync(); + if (firstRender || _twotoneColorChanged) + { + await SetupSvgImg(true); + } + + await base.OnAfterRenderAsync(firstRender); } - protected virtual async Task SetupSvgImg() + private async Task SetupSvgImg(bool rendered = false) { if (Component != null) { return; } + if (!rendered && AvoidPrerendering && Theme == IconThemeType.Twotone) + { + return; + } + string svgClass = Spin ? "anticon-spin" : null; - if (!string.IsNullOrEmpty(IconFont)) - { - var svg = $""; - _svgImg = IconService.GetStyledSvg(svg, svgClass, Width, Height, Fill, Rotate); + var svg = !string.IsNullOrEmpty(IconFont) ? + $"" + : IconService.GetIconImg(Type.ToLowerInvariant(), Theme.ToLowerInvariant()); - StateHasChanged(); - } - else + _svgImg = IconService.GetStyledSvg(svg, svgClass, Width, Height, Fill, Rotate); + + if (rendered && Theme == IconThemeType.Twotone) { - var svg = IconService.GetIconImg(Type.ToLowerInvariant(), Theme.ToLowerInvariant()); - _svgImg = IconService.GetStyledSvg(svg, svgClass, Width, Height, Fill, Rotate); - await InvokeAsync(StateHasChanged); + _svgImg = await IconService.GetTwotoneSvgIcon(_svgImg, TwotoneColor); } + + await InvokeAsync(StateHasChanged); } private async Task HandleOnClick(MouseEventArgs args) @@ -120,5 +146,12 @@ private async Task HandleOnClick(MouseEventArgs args) await OnClick.InvokeAsync(args); } } + + protected override void Dispose(bool disposing) + { + Button?.Icons.Remove(this); + + base.Dispose(disposing); + } } } diff --git a/components/icon/IconFont.razor.cs b/components/icon/IconFont.razor.cs index 5860bc535b..2d5c560eee 100644 --- a/components/icon/IconFont.razor.cs +++ b/components/icon/IconFont.razor.cs @@ -1,17 +1,11 @@ -using System.Threading.Tasks; - -namespace AntDesign +namespace AntDesign { public class IconFont : Icon { - protected override Task SetupSvgImg() + protected override void OnInitialized() { - var svg = $""; - _svgImg = IconService.GetStyledSvg(svg, null, Width, Height, Fill, Rotate); - - StateHasChanged(); - - return Task.CompletedTask; + IconFont = Type; + base.OnInitialized(); } } } diff --git a/components/icon/IconService.cs b/components/icon/IconService.cs index b3112d196c..fd5f4499cf 100644 --- a/components/icon/IconService.cs +++ b/components/icon/IconService.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Threading.Tasks; +using System.Xml.Linq; using Microsoft.JSInterop; #pragma warning disable CA1822 @@ -18,7 +21,7 @@ public IconService(IJSRuntime js) _js = js; } - public static string GetIconImg(string type, string theme) + internal static string GetIconImg(string type, string theme) { var iconImg = IconStore.GetIcon(type, theme); @@ -28,7 +31,7 @@ public static string GetIconImg(string type, string theme) return iconImg; } - public static string GetStyledSvg(string svgImg, string svgClass = null, string width = "1em", string height = "1em", string fill = "currentColor", int rotate = 0) + internal static string GetStyledSvg(string svgImg, string svgClass = null, string width = "1em", string height = "1em", string fill = "currentColor", int rotate = 0) { if (!string.IsNullOrEmpty(svgImg)) { @@ -65,5 +68,31 @@ public bool IconExists(string theme = "", string type = "") return !string.IsNullOrEmpty(icon); } + + public async Task GetTwotoneSvgIcon(string svgImg, string twotoneColor) + { + svgImg = svgImg.Replace("fill=\"#333\"", "fill=\"primaryColor\"") + .Replace("fill=\"#E6E6E6\"", "fill=\"secondaryColor\"") + .Replace("fill=\"#D9D9D9\"", "fill=\"secondaryColor\"") + .Replace("fill=\"#D8D8D8\"", "fill=\"secondaryColor\""); + + var secondaryColors = await _js.InvokeAsync(JSInteropConstants.GenerateColor, twotoneColor); + + var document = XDocument.Load(new StringReader(svgImg)); + var svg = document.Root; + foreach (var path in svg.Nodes().OfType()) + { + if (path.Attribute("fill")?.Value == "secondaryColor") + { + path.SetAttributeValue("fill", secondaryColors[0]); + } + else + { + path.SetAttributeValue("fill", twotoneColor); + } + } + + return svg.ToString(); + } } } diff --git a/components/tsconfig.json b/components/tsconfig.json index 06596bb21a..37a4e387f2 100644 --- a/components/tsconfig.json +++ b/components/tsconfig.json @@ -4,6 +4,7 @@ "noEmitOnError": true, "removeComments": false, "sourceMap": true, + "moduleResolution": "node", "target": "es2015" }, "files": [ "main.ts" ], diff --git a/package.json b/package.json index 545538bf96..b063516e6d 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@types/less": "^3.0.3", "@types/node": "^16.3.2", "@types/resize-observer-browser": "^0.1.3", + "@ant-design/colors": "^6.0.0", "antd-theme-generator": "1.2.2", "babel-core": "^6.26.3", "babel-preset-es2015": "^6.24.1", diff --git a/site/AntDesign.Docs/Demos/Components/Icon/demo/Twotone.razor b/site/AntDesign.Docs/Demos/Components/Icon/demo/Twotone.razor index c450f687fc..0996d3f646 100644 --- a/site/AntDesign.Docs/Demos/Components/Icon/demo/Twotone.razor +++ b/site/AntDesign.Docs/Demos/Components/Icon/demo/Twotone.razor @@ -1,7 +1,18 @@
- - + +
+
+ +@code{ + string color = "#52c41a"; + string[] colors = { "#f759ab", "#2f54eb", "#722ed1", "#1890ff", "#f5222d" }; + int index = 0; + void ChangeColor() + { + color = colors[index++ % 5]; + } +} \ No newline at end of file diff --git a/site/AntDesign.Docs/Demos/Components/Icon/demo/two-tone.md b/site/AntDesign.Docs/Demos/Components/Icon/demo/two-tone.md index 4a4e24bc32..9a007218e8 100644 --- a/site/AntDesign.Docs/Demos/Components/Icon/demo/two-tone.md +++ b/site/AntDesign.Docs/Demos/Components/Icon/demo/two-tone.md @@ -9,6 +9,11 @@ title: 双色图标可以通过 `twoToneColor` 属性设置主题色。 +> 注意:由于利用了JS 互操作来计算颜色,因此在预渲染阶段不能加载颜色。如果不希望在预渲染时展示黑色图标,请使用 `AvoidPrerendering`。 + ## en-US -You can set `twoToneColor` prop to specific primary color for two-tone icons. \ No newline at end of file +You can set `twoToneColor` prop to specific primary color for two-tone icons. + +> Note: Since we used JS interop to calculate colors, we could not load colors during the pre-render phase. +Use 'AvoidPrerendering' if you don't want to show black icons during pre-rendering. \ No newline at end of file diff --git a/site/AntDesign.Docs/Demos/Components/Icon/doc/index.en-US.md b/site/AntDesign.Docs/Demos/Components/Icon/doc/index.en-US.md index ab049d72d1..00c7b63c69 100644 --- a/site/AntDesign.Docs/Demos/Components/Icon/doc/index.en-US.md +++ b/site/AntDesign.Docs/Demos/Components/Icon/doc/index.en-US.md @@ -13,24 +13,13 @@ Semantic vector graphics. Before use icons。 ## API -Common Icon - | Property | Description | Type | Default Value | | --- | --- | --- | --- | | Alt | Alternative text for the icon | string | - | -| ClassName | className of Icon |string | - | +| AvoidPrerendering | Avoid showing black icons during pre-rendering | bool | false | +| Class | class Name of Icon |string | - | | Style | Style properties of icon, like fontSize and color| Css propertities | | Spin | Rotate icon with animation | boolean |- | | Rotate |Rotate by n degrees (not working in IE9)| int | - | | TwoToneColor |Only supports the two-tone icon. Specify the primary color.| string | - | - -We still have three different themes for icons, icon component name is the icon name suffixed by the theme name. - -Custom Icon - -| Property | Description | Type | Default Value | -| --- | --- | --- | --- | -| Style | Style properties of icon, like fontSize and color| CSSProperties | -| Spin | Rotate icon with animation | boolean |- | -| Rotate | Rotate degrees (not working in IE9)| int | - | -| Component |The component used for the root node.| | - | \ No newline at end of file +| Component |The component used for the root node.| | - | diff --git a/site/AntDesign.Docs/Demos/Components/Icon/doc/index.zh-CN.md b/site/AntDesign.Docs/Demos/Components/Icon/doc/index.zh-CN.md index 8bb403a31b..91d8116925 100644 --- a/site/AntDesign.Docs/Demos/Components/Icon/doc/index.zh-CN.md +++ b/site/AntDesign.Docs/Demos/Components/Icon/doc/index.zh-CN.md @@ -18,24 +18,14 @@ cover: https://gw.alipayobjects.com/zos/alicdn/rrwbSt3FQ/Icon.svg ## API -Common Icon | 参数 | 说明 | 类型 | 默认值 | | ---------------- | -------------------------------------------- | ------------- | --------- | -| Alt | Alternative text for the icon | string | - | +| Alt | 备用文本 | string | - | +| AvoidPrerendering | 避免在预渲染时显示黑色图标 | bool | false | | ClassName | 设置图标的样式名 |string | - | | Style | 设置图标的样式,例如 fontSize 和 color| Css propertities | | Spin | 是否有旋转动画 | boolean |- | | Rotate |图标旋转角度(IE9 无效)| int | - | | TwoToneColor |仅适用双色图标。设置双色图标的主要颜色| string | - | - -We still have three different themes for icons, icon component name is the icon name suffixed by the theme name. - -Custom Icon - -| 参数 | 说明 | 类型 | 默认值 | -| ---------------- | -------------------------------------------- | ------------- | --------- | -| Style | 设置图标的样式,例如 fontSize 和 color| CSSProperties | -| Spin | 是否有旋转动画 | boolean |- | -| Rotate | 图标旋转角度(IE9 无效)| int | - | | Component |控制如何渲染图标,通常是一个渲染根标签为 的 React 组件| | - |