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

fix: rework two-color-word effect & implement blinking 重作雙色字效果與實作閃爍 #102

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/components/Row/ColorSegmentBuilder.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import WordSegmentBuilder from "./WordSegmentBuilder";
import { WordSegmentBuilder, TwoColorWordBuilder } from "./WordSegmentBuilder";
import { b2u, isDBCSLead } from "../../js/string_util";
import { symbolTable } from "../../js/symbol_table";

Expand Down Expand Up @@ -56,13 +56,14 @@ export class ColorSegmentBuilder {
return;
}
if (!leadColor.equals(ch.getColor())) {
this.beginSegment(leadColor);
this.wordBuilder.appendTwoColorWord(
text,
this.segs.push(this.wordBuilder.build());
this.wordBuilder = new TwoColorWordBuilder(
this.segs.length,
leadColor,
ch.getColor(),
this.forceWidth
);
this.wordBuilder.appendNormalText(text);
return;
}
const forceWidth = shouldForceWidth(text) ? this.forceWidth : 0;
Expand Down
2 changes: 1 addition & 1 deletion src/components/Row/WordSegmentBuilder/ColorSpan.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import cx from "classnames";
export const ColorSpan = ({ className, colorState, inner }) => (
<span
className={cx(className, `q${colorState.fg}`, `b${colorState.bg}`, {
[`qq${colorState.bg}`]: colorState.blink
qq: colorState.blink
})}
>
{inner}
Expand Down
34 changes: 24 additions & 10 deletions src/components/Row/WordSegmentBuilder/TwoColorWord.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,33 @@ import cx from "classnames";
import { forceWidthStyle } from "./ForceWidthWord";

/**
* TODO: add blinking.
* TwoColorWord implements the two-color-word effect,
* where the first half ("head") and the last half ("tail")
* of a fullwidth character ("word") have different colors.
*
* The two-color-word effect is achieved
* by using two half-word pseudo elements (enabled by CSS class .o),
* one for the left half (::before; controlled by non-prefixed CSS classes)
* and one for the right half (::after; controlled by CSS classes prefixed with 'r'),
* so that the two halves of the word can be controlled independently.
*
* Additionally, to make the text selection appear normal,
* the real element is made invisible and placed on top of the pseudo elements.
*/
export const TwoColorWord = ({ colorLead, colorTail, forceWidth, text }) => (
<span
className={cx({
[`q${colorLead.fg}`]: colorLead.fg === colorTail.fg,
[`w${colorLead.fg}`]: colorLead.fg !== colorTail.fg,
[`q${colorTail.fg}`]: colorLead.fg !== colorTail.fg,
o: colorLead.fg !== colorTail.fg,
[`b${colorLead.bg}`]: colorLead.bg === colorTail.bg,
[`b${colorLead.bg}b${colorTail.bg}`]: colorLead.bg !== colorTail.bg,
wpadding: forceWidth
})}
className={cx(
"o",
`q${colorLead.fg}`,
`rq${colorTail.fg}`,
`b${colorLead.bg}`,
`rb${colorTail.bg}`,
{
qq: colorLead.blink,
rqq: colorTail.blink,
wpadding: forceWidth
}
)}
style={forceWidthStyle(forceWidth)}
data-text={text}
>
Expand Down
34 changes: 23 additions & 11 deletions src/components/Row/WordSegmentBuilder/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,36 @@ export class WordSegmentBuilder {
);
}

appendTwoColorWord(text, colorLead, colorTail, forceWidth) {
this.inner.push(
<TwoColorWord
key={this.inner.length}
text={text}
colorLead={colorLead}
colorTail={colorTail}
forceWidth={forceWidth}
build() {
return (
<ColorSpan
key={this.key}
colorState={this.colorState}
inner={this.inner}
/>
);
}
}

export class TwoColorWordBuilder extends WordSegmentBuilder {
constructor(key, colorState, colorTail, forceWidth) {
super(key, colorState);
this.colorTail = colorTail;
this.forceWidth = forceWidth;
}

isLastSegmentSameColor(color) {
return false; // forbid appending
}

build() {
return (
<ColorSpan
<TwoColorWord
key={this.key}
colorState={this.colorState}
inner={this.inner}
colorLead={this.colorState}
colorTail={this.colorTail}
forceWidth={this.forceWidth}
text={this.inner}
/>
);
}
Expand Down
Loading