PixiJs cannot load image by loader - vue.js

I'm a beginner on PixiJs.
I want show a sprite image as some example, but I'm defeated.
The framework is Vue with Typescript.
I used vue-cli to generate a project ,and only modified the App.vue file like this:
<template>
<img alt="Vue logo" src="./assets/logo.png">
<!-- <HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/> -->
<div ref='iv'></div>
</template>
<script lang="ts">
// import logo from '#/assets/logo.png';
import { Options, Vue } from 'vue-class-component';
import HelloWorld from './components/HelloWorld.vue';
import * as PIXI from 'pixi.js'
#Options({
components: {
HelloWorld,
},
})
export default class App extends Vue {
refs():any{
return this.$refs
}
app=new PIXI.Application({width:400,height:300})
setup(loader:PIXI.Loader){
const bunny = new PIXI.Sprite(loader.resources.logo.texture);
this.app.stage.addChild(bunny);
}
mounted(){
this.refs().iv.appendChild(this.app.view)
this.app.loader.add("logo","#/assets/logo.png").load(this.setup)
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
but if I use import to load image, like:
import logo from '#/assets/logo.png';
...
mounted(){
...
let s=PIXI.Sprite.from(logo)
this.app.stage.addChild(s)
...
}
It works.
What's my mistake?
How can I use the loader correctly?

Related

Vuejs - vue2-editor not accepting all tags

I have implemented the vue2-editor, and here is the below code
<div id="app">
<vue-editor v-model="content"></vue-editor>
<div v-html="content"></div>
</div>
</template>
<script>
import { VueEditor } from "vue2-editor";
export default {
components: {
VueEditor
},
data() {
return {
content: "<p>Some initial content</p>"
};
}
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* text-align: center; */
color: #2c3e50;
margin-top: 60px;
}
</style>
If the content is wrapped with <p> tag then the editor shows the content correctly, if it is wrapped with <div> tag then it throws an exception,
Exception: Uncaught TypeError: Cannot read properties of undefined (reading 'emit')
Few more tags with same issue (<title>,<small>,<span>)
sandbox link for reference: https://codesandbox.io/s/liz23?file=/src/App.vue:0-553
Thanks
Check this codesanbox I made: https://codesandbox.io/s/stack-72533246-vue2editor-div-bug-z8qqp8?file=/src/App.vue
It looks that is a bug of the library, meanwhile it gets fixed you can use this workaound.
import { VueEditor, Quill } from "vue2-editor";
const Block = Quill.import("blots/block");
Block.tagName = "DIV";
Quill.register(Block, true);
Refer to this github issue thread for more info: https://github.com/davidroyer/vue2-editor/issues/63

Can't access functions from package installed with npm

I'm trying to access the different methods from tinyMCE, but it can't find get, setContent or insertContent. Anyone got any ideas how I can access these? The following code is a copy from their documentation.
Here is my code so far:
App.vue:
<template>
<div id="app">
<Editor id="test"></Editor>
<button #click="insertData">Test</button>
</div>
</template>
<script>
export default {
name: 'App',
components: {
Editor
},
methods: {
insertData: function () {
Editor.get("test").setContent("This is a test.")
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false;
// es modulesc
var commonjsrequire = require('commonjs-require');
// NOTE: default needed after require
var Editor = require('#tinymce/tinymce-vue').default;
Vue.component('Editor',
() => import('#tinymce/tinymce-vue')
);
new Vue({
render: function (h) { return h(App) },
}).$mount('#app')
The functions you are after are tied to the tinymce global object. While you define an Editor component in the context of the application the actual API calls for TinyMCE are part of the tinymce global object.
For example:
tinymce.get("test").setContent("<p>This is a test.</p>")

How to properly use slot inside of vue js web component and apply styles

I have come across an issue where the implementation of slots in a webcomponent is not functioning as expected. My understanding of Web Components, Custom Elements and Slots is that elements rendered in a slot should inherit their style from the document and not the Shadow DOM however the element in the slot is actually being added to the Shadow DOM and therefore ignoring the global styles. I have created the following example to illustrate the issue that I am having.
shared-ui
This is a Vue application that is compiled to web components using the cli (--target wc --name shared-ui ./src/components/*.vue)
CollapseComponent.vue
<template>
<div :class="[$style.collapsableComponent]">
<div :class="[$style.collapsableHeader]" #click="onHeaderClick" :title="title">
<span>{{ title }}</span>
</div>
<div :class="[$style.collapsableBody]" v-if="expanded">
<slot name="body-content"></slot>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
#Component({})
export default class CollapsableComponent extends Vue {
#Prop({ default: "" })
title!: string;
#Prop({default: false})
startExpanded!: boolean;
private expanded: boolean = false;
constructor() {
super();
this.expanded = this.startExpanded;
}
get isVisible(): boolean {
return this.expanded;
}
onHeaderClick(): void {
this.toggle();
}
public toggle(expand?: boolean): void {
if(expand === undefined) {
this.expanded = !this.expanded;
}
else {
this.expanded = expand;
}
this.$emit(this.expanded? 'expand' : 'collapse');
}
public expand() {
this.expanded = true;
}
public collapse() {
this.expanded = false;
}
}
</script>
<style module>
:host {
display: block;
}
.collapsableComponent {
background-color: white;
}
.collapsableHeader {
border: 1px solid grey;
background: grey;
height: 35px;
color: black;
border-radius: 15px 15px 0 0;
text-align: left;
font-weight: bold;
line-height: 35px;
font-size: 0.9rem;
padding-left: 1em;
}
.collapsableBody {
border: 1px solid black;
border-top: 0;
border-radius: 0 0 10px 10px;
padding: 1em;
}
</style>
shared-ui-consumer
This is a vue application that imports the shared-ui web component using a standard script include file.
App.vue
<template>
<div id="app">
<shared-ui title="Test">
<span class="testClass" slot="body-content">
Here is some text
</span>
</shared-ui>
</div>
</template>
<script lang="ts">
import 'vue'
import { Component, Vue } from 'vue-property-decorator';
#Component({ })
export default class App extends Vue {
}
</script>
<style lang="scss">
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.testClass{
color: red;
}
</style>
main.ts
import Vue from "vue";
import App from "./App.vue";
Vue.config.productionTip = false;
// I needed to do this so the web component could reference Vue
(window as any).Vue = Vue;
new Vue({
render: h => h(App),
}).$mount('#app');
In this example I would expect the content inside the container to have red text however because Vue is cloning the element into the Shadow DOM the .testClass style is being ignored and the text is rendered with a black fill.
How can I apply .testClass to the element inside of my web component?
Ok, so I managed to find a workaround for this that uses native slots and renders the child components correctly in the correct place in the DOM.
In the mounted event wire up the next tick to replace the innerHtml of your slot container with a new slot. You can get fancy and do some cool replacements for named slots and whatnot but this should suffice for illustrating the workaround.
shared-ui
This is a Vue application that is compiled to web components using the cli (--target wc --name shared-ui ./src/components/*.vue)
CollapseComponent.vue
<template>
<div :class="[$style.collapsableComponent]">
<div :class="[$style.collapsableHeader]" #click="onHeaderClick" :title="title">
<span>{{ title }}</span>
</div>
<div ref="slotContainer" :class="[$style.collapsableBody]" v-if="expanded">
<slot></slot>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from 'vue-property-decorator'
#Component({})
export default class CollapsableComponent extends Vue {
#Prop({ default: "" })
title!: string;
#Prop({default: false})
startExpanded!: boolean;
private expanded: boolean = false;
constructor() {
super();
this.expanded = this.startExpanded;
}
get isVisible(): boolean {
return this.expanded;
}
onHeaderClick(): void {
this.toggle();
}
//This is where the magic is wired up
mounted(): void {
this.$nextTick().then(this.fixSlot.bind(this));
}
// This is where the magic happens
fixSlot(): void {
// remove all the innerHTML that vue has place where the slot should be
this.$refs.slotContainer.innerHTML = '';
// replace it with a new slot, if you are using named slot you can just add attributes to the slot
this.$refs.slotContainer.append(document.createElement('slot'));
}
public toggle(expand?: boolean): void {
if(expand === undefined) {
this.expanded = !this.expanded;
}
else {
this.expanded = expand;
}
this.$emit(this.expanded? 'expand' : 'collapse');
}
public expand() {
this.expanded = true;
}
public collapse() {
this.expanded = false;
}
}
</script>
<style module>
:host {
display: block;
}
.collapsableComponent {
background-color: white;
}
.collapsableHeader {
border: 1px solid grey;
background: grey;
height: 35px;
color: black;
border-radius: 15px 15px 0 0;
text-align: left;
font-weight: bold;
line-height: 35px;
font-size: 0.9rem;
padding-left: 1em;
}
.collapsableBody {
border: 1px solid black;
border-top: 0;
border-radius: 0 0 10px 10px;
padding: 1em;
}
</style>
shared-ui-consumer
This is a vue application that imports the shared-ui web component using a standard script include file.
App.vue
<template>
<div id="app">
<shared-ui title="Test">
<span class="testClass" slot="body-content">
Here is some text
</span>
</shared-ui>
</div>
</template>
<script lang="ts">
import 'vue'
import { Component, Vue } from 'vue-property-decorator';
#Component({ })
export default class App extends Vue {
}
</script>
<style lang="scss">
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
.testClass{
color: red;
}
</style>
main.ts
import Vue from "vue";
import App from "./App.vue";
Vue.config.productionTip = false;
// I needed to do this so the web component could reference Vue
(window as any).Vue = Vue;
new Vue({
render: h => h(App),
}).$mount('#app');

How to use UIkit with Vue?

I installed uikit with yarn.
yarn add uikit
And additionally less-loader, less and css-loader because this site said so.
Now I tried using UIkit in my App.vue like so.
<template>
<div id="app">
<div class="uk-alert-primary" uk-alert>
<a class="uk-alert-close" uk-close></a>
<p>This is a text!</p>
</div>
<table class="uk-table uk-table-striped">
<tr><td>Hello World!</td></tr>
<tr><td>Hello World!</td></tr>
<tr><td>Hello World!</td></tr>
</table>
</div>
</template>
<script>
import UIkit from 'uikit';
import Icons from 'uikit/dist/js/uikit-icons';
UIkit.use(Icons);
export default {
mounted: function() {
this.getTestJson();
},
methods: {
getTestJson: function() {
this.$http.get('http://localhost:8090/test').then((res) => {
console.log(res.body)
});
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
This is not enough, the UIkit components are not displayed properly. What else do I have to do?
Do I have to use vuikit?
This link will help, and basically you need to do the following:
After installing uikit package, add this code to App.vue
<style lang="less">
#import "../node_modules/uikit/src/less/uikit.less";
</style>
And then add this code to main.js
import uk from 'uikit'
import Icons from 'uikit/dist/js/uikit-icons'
uk.use(Icons)
You can also add global mixin for uk object in case you wanted to use UIKit JavaScript functionality anywhere in your components e.g. this.uk.toggle('#toggle-elm').toggle():
Vue.mixin({
data: function () {
return {
get uk () {
return uk
}
}
}
})
new Vue({
el: '#app',
...

Not able to call Vue component in vue cli application

I am trying to create the component for tile which can be used in multiple views. I have called the component in view but it is not working
Code of component (Tile.vue)
<template>
<div class="tile">
<label class="title">Tile Title</label>
</div>
</template>
<script>
export default {
name: 'CustomTile'
}
</script>
<style scoped lang="less">
.tile { width:248px;
height: 126px;
background-color:#e4e4e4;
.title {
padding-left: 15px;
}
}
</style>
code of view (Report.vue) where I am trying to call above component
<template>
<div>
<div class="topnav">
<button type="button">Expand/Collapse</button>
</div>
<div class="content">
<CustomTile></CustomTile>
</div>
</div>
</template>
<script>
import CustomTile from '#/components/Tile.vue'
export default {
name: 'Report'
}
</script>
<style scoped lang="less">
.topnav {
overflow: hidden;
background-color: #d6d6d6;
}
.topnav a {
float: left;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}.topnav a.active {
background-color: #4CAF50;
color: white;
}
.content {
height:500px;
width:500px;
}
</style>
CustomTile is not getting rendered. I am not able to figure out what/where is the problem.
You need to properly import the component in the parent where you want to use it and register it:
Report.vue:
<script>
import CustomTile from '#/components/Tile.vue'
export default {
name: 'Report',
components: {
CustomTile
}
}
</script>
And then, since CustomTile is a CamelCase component name, you need to use the following notation:
<custom-tile></custom-tile>