如何通过CKEditor5 API插入自定义尺寸的图片?
CKEditor5插入图片时width/height属性被忽略的解决方法
CKEditor5的模型-视图分离架构下,默认不会自动将HTML中<img>的width/height属性映射到编辑器模型的图片节点,这就是你插入内容时尺寸被忽略的核心原因。结合你使用的Image、ImageResize插件,这里提供两种可行的解决思路:
方案一:自定义数据转换规则(适合能控制编辑器初始化的场景)
通过扩展Image插件的转换配置,让数据处理器在dataToModel和modelToView阶段自动处理尺寸属性:
// 编辑器初始化时添加配置(如果有权限修改初始化代码) ClassicEditor.create(document.querySelector('#editor'), { plugins: [Image, ImageResize, /* 其他插件 */], image: { resizeUnit: 'px', converters: { // 从HTML视图转换到模型时,提取width/height属性 dataToModel: [ dispatcher => { dispatcher.on('element:img', (evt, data, conversionApi) => { const viewImg = data.viewItem; const modelImg = data.modelItem; if (!modelImg) return; const width = viewImg.getAttribute('width'); if (width) { conversionApi.writer.setAttribute('width', parseInt(width, 10), modelImg); } const height = viewImg.getAttribute('height'); if (height) { conversionApi.writer.setAttribute('height', parseInt(height, 10), modelImg); } }, { priority: 'low' }); } ], // 从模型转换到视图时,将尺寸属性转为行内样式 modelToView: [ dispatcher => { // 处理width属性 dispatcher.on('attribute:width:image', (evt, data, conversionApi) => { const viewImg = conversionApi.mapper.toViewElement(data.item); if (!viewImg) return; if (data.attributeNewValue !== null) { conversionApi.writer.setStyle('width', `${data.attributeNewValue}px`, viewImg); } else { conversionApi.writer.removeStyle('width', viewImg); } }); // 处理height属性 dispatcher.on('attribute:height:image', (evt, data, conversionApi) => { const viewImg = conversionApi.mapper.toViewElement(data.item); if (!viewImg) return; if (data.attributeNewValue !== null) { conversionApi.writer.setStyle('height', `${data.attributeNewValue}px`, viewImg); } else { conversionApi.writer.removeStyle('height', viewImg); } }); } ] } } });
方案二:手动处理插入的模型片段(适合无法修改编辑器初始化的场景)
如果是第三方集成的编辑器(比如Zendesk内嵌的),无法修改初始化配置,可以在插入前手动提取视图中的尺寸,再给模型节点设置属性:
const text = '<p>Some text before <img src="https://www.example.com/someImg200x200.png" width="100" height="100" /> Some text after</p>'; ckEditorInstance.model.change((writer) => { const viewFragment = ckEditorInstance.data.processor.toView(text); // 先收集所有img的尺寸信息 const imgSizes = []; viewFragment.forEach(node => { if (node.is('element', 'p')) { node.forEach(child => { if (child.is('element', 'img')) { imgSizes.push({ src: child.getAttribute('src'), width: parseInt(child.getAttribute('width'), 10), height: parseInt(child.getAttribute('height'), 10) }); } }); } }); const modelFragment = ckEditorInstance.data.toModel(viewFragment); // 遍历模型片段中的图片节点,设置尺寸属性 modelFragment.forEach(node => { if (node.is('element', 'paragraph')) { node.forEach(child => { if (child.is('element', 'image')) { const imgInfo = imgSizes.find(i => i.src === child.getAttribute('src')); if (imgInfo) { if (imgInfo.width) writer.setAttribute('width', imgInfo.width, child); if (imgInfo.height) writer.setAttribute('height', imgInfo.height, child); } } }); } }); writer.model.insertContent(modelFragment, ckEditorInstance.model.document.selection); });
注意事项
- 如果使用
ZendeskImagePlugin,需要确保自定义转换器的优先级(比如priority: 'low')不会被插件自带的转换规则覆盖。 - 尺寸值建议转为整数,避免CKEditor的验证逻辑过滤非数值的属性值。
内容的提问来源于stack exchange,提问作者mrzalais
相关产品推荐
相关产品推荐

