I'm trying to use a CSS mask in my Vue component. I need to complete the implementation of the toSvg
function below. This will render the Vue VNode coming from this.$slots.default
to an SVG string.
<script>
export default {
computed: {
maskImage() {
const svg = this.toSvg(this.$slots.default);
const encodedSvg = btoa(svg);
return `url('data:image/svg+xml;base64,${encodedSvg}')`;
},
},
methods: {
toSvg(vnode) {
// TODO: How can I convert the VNode to a string like the one below?
// In React, I could use const svg = ReactDOMServer.renderToStaticMarkup(vnode);
return `<svg viewBox="0 0 260 68" xmlns="http://www.w3.org/2000/svg">
<rect x="80" y="32" width="160" height="12" rx="2" />
<rect width="180" height="20" rx="2" />
<rect x="80" y="52" width="95" height="12" rx="2" />
<rect y="26" width="68" height="42" rx="2" />
</svg>`;
},
},
render(createElement) {
return createElement("div", {
attrs: {
class: "skeleton",
style: `-webkit-mask-image: ${this.maskImage}; mask-image: ${this.maskImage};`,
},
});
},
};
</script>
<style lang="scss">
.skeleton {
animation: skeleton-animation 2s infinite linear;
background: linear-gradient(to right, hsl(30, 1, 99) 0%, hsl(30, 2, 95) 30%, hsl(30, 2, 95) 70%, hsl(30, 1, 99) 100%) 0 0 / 200% 100% hsl(30, 2, 95);
overflow: hidden;
position: relative;
width: 200px;
height: 100px;
@keyframes skeleton-animation {
100% {
background-position: -200% 0;
}
}
}
</style>
Usage example:
<u-skeleton>
<svg viewBox="0 0 260 68" xmlns="http://www.w3.org/2000/svg">
<rect x="80" y="32" width="160" height="12" rx="2" />
<rect width="180" height="20" rx="2" />
<rect x="80" y="52" width="95" height="12" rx="2" />
<rect y="26" width="68" height="42" rx="2" />
</svg>
</u-skeleton>
Shows as:
Uses
Vue.extend
to construct one SVG component constructor, insiderender function
of the constructor, it rendersslots.default
.Next step is create its instance, then
mount()
and get the compiled html.