I am working on a rich text editor using ProseMirror and have implemented a custom nodeView
for rendering text with SVG gradient effects. However, I’ve encountered an issue where the SVG defs
section disappears during the compositionstart
event when typing in Chinese, and it only reappears after the compositionend
event.
Here’s a detailed description of the problem:
- When I start typing using the Chinese input method (triggering the
compositionstart
event), thedefs
part of the SVG is not visible. - Once I finish typing (triggering the
compositionend
event), thedefs
section reappears as expected.
I have tried the following to address this issue:
- Ensuring that the SVG and
defs
elements are correctly created within thenodeView
. - Utilizing
requestAnimationFrame
for optimizing DOM updates.
Despite these efforts, the problem remains unresolved. Below is a relevant snippet of my code:
export const initProsemirrorEditor = (dom: Element, content: string, props = {}) => {
const editor = new EditorView(dom, {
state: EditorState.create({
doc: createDocument(content),
plugins: buildPlugins(schema),
}),
...props,
nodeViews: {
'svgGradientText': (node) => {
let dom = document.createElement('span');
dom.className = 'svg-gradient-text';
dom.setAttribute('data-gradient-id', node.attrs.id);
dom.style.display = 'inline-block';
dom.style.maxWidth = '100%'
const xmlNS = 'http://www.w3.org/2000/svg'
let text = document.createElementNS(xmlNS, 'text') as any;
text.setAttribute('x', '50%');
text.setAttribute('y', '50%');
text.setAttribute('style', 'text-anchor: middle; dominant-baseline: middle; fill: url(#' + node.attrs.id + '); text-shadow: 0 8px 0 #333; stroke-width: 6px; stroke: #333; paint-order: stroke; stroke-linejoin: round;font-size:40px');
let svg = document.createElementNS(xmlNS, 'svg');
let defs = document.createElementNS(xmlNS, 'defs');
let linearGradient = document.createElementNS(xmlNS, 'linearGradient');
linearGradient.setAttribute('id', node.attrs.id);
linearGradient.setAttribute('x1', '0');
linearGradient.setAttribute('y1', '0');
linearGradient.setAttribute('x2', '0');
linearGradient.setAttribute('y2', '1');
let stop1 = document.createElementNS(xmlNS, 'stop');
stop1.setAttribute('offset', '0%');
stop1.setAttribute('stop-color', '#FFCF02');
linearGradient.appendChild(stop1);
let stop2 = document.createElementNS(xmlNS, 'stop');
stop2.setAttribute('offset', '100%');
stop2.setAttribute('stop-color', '#FF7352');
linearGradient.appendChild(stop2);
defs.appendChild(linearGradient);
svg.appendChild(defs);
svg.appendChild(text)
dom.appendChild(svg)
nextTick(() => {
const bbox = text.getBBox();
if (bbox.width === 0) return
svg.setAttribute('width', bbox.width + 10);
svg.setAttribute('height', bbox.height + 10);
})
return {
dom,
contentDOM: text,
}
}
},
})
return editor
}
const svgGradientText: MarkSpec = {
group: 'inline',
attrs: {
id: { default: 'gradient' },
},
toDOM: mark => ['span', { 'class': 'svg-gradient-text', 'data-gradient-id': mark.attrs.id }, 0],
parseDOM: [{
tag: 'span.svg-gradient-text',
getAttrs: dom => {
const id = dom.getAttribute('data-gradient-id');
return { id };
}
}]
}
I am hoping to find a solution through the community’s help to ensure that the defs
part of the SVG is displayed correctly even during the composition input phase of the Chinese input method.
Has anyone encountered a similar issue? Or do you have any suggestions that could help me resolve this problem?
I would greatly appreciate your time and assistance!