Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(icon): two-tone color icon implements #2513

Merged
merged 11 commits into from
Jun 18, 2022
1 change: 1 addition & 0 deletions components/core/JsInterop/JSInteropConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
2 changes: 2 additions & 0 deletions components/core/JsInterop/interop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
8 changes: 4 additions & 4 deletions components/core/JsInterop/modules/components/iconHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
2 changes: 1 addition & 1 deletion components/icon/Icon.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@namespace AntDesign
@inherits AntDomComponentBase

<span role="img" alt="@Alt" class="@ClassMapper.Class" style="@Style" id="@Id" @onclick="HandleOnClick" @onclick:stopPropagation="StopPropagation" tabindex="@TabIndex" @ref="Ref">
<span role="img" alt="@Alt" class="@ClassMapper.Class" style="@Style" id="@Id" tabindex="@TabIndex" @ref="Ref" @attributes="_attributes" @onclick:stopPropagation="StopPropagation">
@if (Component == null)
{
@((MarkupString) _svgImg)
Expand Down
87 changes: 60 additions & 27 deletions components/icon/Icon.razor.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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; }

Expand All @@ -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; }
Expand All @@ -51,20 +67,17 @@ public partial class Icon : AntDomComponentBase
[Parameter]
public EventCallback<MouseEventArgs> 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<string, object> _attributes = new();

protected override async Task OnInitializedAsync()
{
Expand All @@ -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 = $"<svg><use xlink:href=#{IconFont} /></svg>";
_svgImg = IconService.GetStyledSvg(svg, svgClass, Width, Height, Fill, Rotate);
var svg = !string.IsNullOrEmpty(IconFont) ?
$"<svg><use xlink:href=#{IconFont} /></svg>"
: 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)
Expand All @@ -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);
}
}
}
14 changes: 4 additions & 10 deletions components/icon/IconFont.razor.cs
Original file line number Diff line number Diff line change
@@ -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 = $"<svg><use xlink:href=#{Type} /></svg>";
_svgImg = IconService.GetStyledSvg(svg, null, Width, Height, Fill, Rotate);

StateHasChanged();

return Task.CompletedTask;
IconFont = Type;
base.OnInitialized();
}
}
}
33 changes: 31 additions & 2 deletions components/icon/IconService.cs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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);

Expand All @@ -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))
{
Expand Down Expand Up @@ -65,5 +68,31 @@ public bool IconExists(string theme = "", string type = "")

return !string.IsNullOrEmpty(icon);
}

public async Task<string> 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<string[]>(JSInteropConstants.GenerateColor, twotoneColor);

var document = XDocument.Load(new StringReader(svgImg));
var svg = document.Root;
foreach (var path in svg.Nodes().OfType<XElement>())
{
if (path.Attribute("fill")?.Value == "secondaryColor")
{
path.SetAttributeValue("fill", secondaryColors[0]);
}
else
{
path.SetAttributeValue("fill", twotoneColor);
}
}

return svg.ToString();
}
}
}
1 change: 1 addition & 0 deletions components/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"noEmitOnError": true,
"removeComments": false,
"sourceMap": true,
"moduleResolution": "node",
"target": "es2015"
},
"files": [ "main.ts" ],
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
15 changes: 13 additions & 2 deletions site/AntDesign.Docs/Demos/Components/Icon/demo/Twotone.razor
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
<div>
<Icon Type="smile" Theme="twotone" Height="2em" Width="2em" />
<Icon Type="heart" Theme="twotone" TwotoneColor="#eb2f96" Height="2em" Width="2em" />
<Icon Type="check-circle" Theme="twotone" TwotoneColor="#52c41a" Height="2em" Width="2em" />
<Icon Type="heart" Theme="twotone" TwotoneColor="#eb2f96" Height="2em" Width="2em" AvoidPrerendering />
<Icon Type="check-circle" Theme="twotone" TwotoneColor="@color" Height="2em" Width="2em" OnClick="ChangeColor"/>
</div>
<br/>

<Button OnClick="ChangeColor">Change Color</Button>

@code{
string color = "#52c41a";
string[] colors = { "#f759ab", "#2f54eb", "#722ed1", "#1890ff", "#f5222d" };
int index = 0;
void ChangeColor()
{
color = colors[index++ % 5];
}
}
7 changes: 6 additions & 1 deletion site/AntDesign.Docs/Demos/Components/Icon/demo/two-tone.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ title:

双色图标可以通过 `twoToneColor` 属性设置主题色。

> 注意:由于利用了JS 互操作来计算颜色,因此在预渲染阶段不能加载颜色。如果不希望在预渲染时展示黑色图标,请使用 `AvoidPrerendering`。

## en-US

You can set `twoToneColor` prop to specific primary color for two-tone icons.
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.
17 changes: 3 additions & 14 deletions site/AntDesign.Docs/Demos/Components/Icon/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.| | - |
| Component |The component used for the root node.| | - |
14 changes: 2 additions & 12 deletions site/AntDesign.Docs/Demos/Components/Icon/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |控制如何渲染图标,通常是一个渲染根标签为 <svg> 的 React 组件| | - |