Merge pull request #266 from marcosmoura/components/mdImage

Components/md image
This commit is contained in:
Marcos Moura 2016-12-28 03:41:36 -02:00 committed by GitHub
commit 28e47c71db
20 changed files with 257 additions and 39 deletions

View file

@ -75,6 +75,10 @@
<router-link exact to="/components/icon">Icon</router-link>
</md-list-item>
<md-list-item class="md-inset">
<router-link exact to="/components/image-loader">Image Loader</router-link>
</md-list-item>
<md-list-item class="md-inset">
<router-link exact to="/components/input">Input</router-link>
</md-list-item>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
docs/src/assets/joker-1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
docs/src/assets/joker-2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

BIN
docs/src/assets/joker-3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

View file

@ -0,0 +1,103 @@
<template>
<page-content page-title="Components - Image Loader">
<docs-component>
<div slot="description">
<p>Illustrations and photographs may load and transition in three phases by staggering opacity, exposure, and saturation levels.</p>
</div>
<div slot="api">
<api-table name="md-image">
<md-table slot="properties">
<md-table-header>
<md-table-row>
<md-table-head>Name</md-table-head>
<md-table-head>Type</md-table-head>
<md-table-head>Description</md-table-head>
</md-table-row>
</md-table-header>
<md-table-body>
<md-table-row>
<md-table-cell>md-src</md-table-cell>
<md-table-cell><code>String</code></md-table-cell>
<md-table-cell>The image source. Accepts any image file extension.</md-table-cell>
</md-table-row>
</md-table-body>
</md-table>
</api-table>
</div>
<div slot="example">
<example-box card-title="Default">
<div slot="demo">
<md-button class="md-primary md-raised" @click="loadImage">Load Image</md-button>
<md-button class="md-primary md-raised" @click="clearImage">Clear Image</md-button>
<div>
<md-image :md-src="src"></md-image>
</div>
</div>
<div slot="code">
<code-block lang="xml">
&lt;md-button class=&quot;md-primary md-raised&quot; @click=&quot;loadImage&quot;&gt;Load Image&lt;/md-button&gt;
&lt;md-button class=&quot;md-primary md-raised&quot; @click=&quot;clearImage&quot;&gt;Clear Image&lt;/md-button&gt;
&lt;div&gt;
&lt;md-image :md-src=&quot;src&quot;&gt;&lt;/md-image&gt;
&lt;/div&gt;
</code-block>
<code-block lang="xml">
export default {
data: () => ({
src: null
}),
methods: {
loadImage() {
let options = [
'assets/joker-1.jpg',
'assets/joker-2.jpg',
'assets/joker-3.jpg',
'assets/card-image-1.jpg',
'assets/card-image-2.jpg'
];
this.src = options[Math.floor(Math.random() * 5)];
},
clearImage() {
this.src = null;
}
}
};
</code-block>
</div>
</example-box>
</div>
</docs-component>
</page-content>
</template>
<script>
export default {
data: () => ({
src: null
}),
methods: {
loadImage() {
let options = [
'assets/joker-1.jpg',
'assets/joker-2.jpg',
'assets/joker-3.jpg',
'assets/card-image-1.jpg',
'assets/card-image-2.jpg'
];
this.src = options[Math.floor(Math.random() * 5)];
},
clearImage() {
this.src = null;
}
}
};
</script>

View file

@ -15,6 +15,7 @@ const Checkbox = (resolve) => require(['./pages/components/Checkbox'], resolve);
const Chips = (resolve) => require(['./pages/components/Chips'], resolve);
const Dialog = (resolve) => require(['./pages/components/Dialog'], resolve);
const Icon = (resolve) => require(['./pages/components/Icon'], resolve);
const ImageLoader = (resolve) => require(['./pages/components/ImageLoader'], resolve);
const InkRipple = (resolve) => require(['./pages/components/InkRipple'], resolve);
const Input = (resolve) => require(['./pages/components/Input'], resolve);
const List = (resolve) => require(['./pages/components/List'], resolve);
@ -114,6 +115,11 @@ const components = [
name: 'components:icon',
component: Icon
},
{
path: '/components/image-loader',
name: 'components:image-loader',
component: ImageLoader
},
{
path: '/components/ink-ripple',
name: 'components:ink-ripple',

View file

@ -6,40 +6,7 @@
</template>
<script>
const getImageAlpha = (image, onLoad) => {
let canvas = document.createElement('canvas');
image.onload = function() {
let colorSum = 0;
let ctx;
let imageData;
let imageMetadata;
let r;
let g;
let b;
let average;
canvas.width = this.width;
canvas.height = this.height;
ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0);
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
imageMetadata = imageData.data;
for (let x = 0, len = imageMetadata.length; x < len; x += 4) {
r = imageMetadata[x];
g = imageMetadata[x + 1];
b = imageMetadata[x + 2];
average = Math.floor((r + g + b) / 3);
colorSum += average;
}
onLoad(Math.floor(colorSum / (this.width * this.height)));
};
};
import getImageLightness from '../../core/utils/getImageLightness';
export default {
props: {
@ -82,7 +49,7 @@
let image = this.$el.querySelector('img');
if (image && (this.mdTextScrim || this.mdSolid)) {
getImageAlpha(image, (lightness) => {
getImageLightness(image, (lightness) => {
let limit = 256;
let darkness = (Math.abs(limit - lightness) * 100 / limit + 15) / 100;

View file

@ -0,0 +1,8 @@
import mdImage from './mdImage.vue';
import mdImageTheme from './mdImage.theme';
export default function install(Vue) {
Vue.component('md-image', Vue.extend(mdImage));
Vue.material.styles.push(mdImageTheme);
}

View file

@ -0,0 +1,19 @@
@import '../../core/stylesheets/variables.scss';
$transition-duration: 2.2s;
.md-image {
opacity: 0;
filter: saturate(20%);
&.md-black-output {
filter: brightness(.4) saturate(20%);
}
&.md-loaded {
opacity: 1;
filter: saturate(100%);
transition: opacity $transition-duration/2 $swift-ease-out-timing-function,
filter $transition-duration .3s $swift-ease-out-timing-function;
}
}

View file

@ -0,0 +1,5 @@
.THEME_NAME {
&.md-image {
}
}

View file

@ -0,0 +1,64 @@
<template>
<img :src="mdSrc" class="md-image" :class="classes">
</template>
<style lang="scss" src="./mdImage.scss"></style>
<script>
import getImageLightness from '../../core/utils/getImageLightness';
export default {
props: {
mdSrc: String
},
data: () => ({
loaded: false,
applyBlack: true,
imageElement: null
}),
watch: {
mdSrc() {
this.createImage();
}
},
computed: {
classes() {
return {
'md-loaded': this.loaded,
'md-black-output': this.applyBlack
};
}
},
methods: {
analyzeLightness(image) {
getImageLightness(image, (lightness) => {
let limit = 256;
let darkness = (Math.abs(limit - lightness) * 100 / limit + 15) / 100;
if (darkness >= 0.7) {
this.applyBlack = true;
}
this.$nextTick(() => {
this.loaded = true;
});
});
},
createImage() {
this.loaded = false;
this.applyBlack = false;
this.imageElement = null;
if (this.mdSrc) {
this.imageElement = document.createElement('img');
this.imageElement.crossOrigin = '';
this.imageElement.src = this.mdSrc;
this.analyzeLightness(this.imageElement);
}
}
},
created() {
this.createImage();
}
};
</script>

View file

@ -134,10 +134,11 @@
return idList.indexOf(id);
},
calculateIndicatorPos() {
if (this.$refs.tabHeader) {
let activeTab = this.$refs.tabHeader && this.$refs.tabHeader[this.activeTabNumber];
if (activeTab) {
let tabsWidth = this.$el.offsetWidth;
let activeTab = this.$refs.tabHeader[this.activeTabNumber];
let left = activeTab ? activeTab.offsetLeft : 0;
let left = activeTab.offsetLeft;
let right = tabsWidth - left - activeTab.offsetWidth;
this.$refs.indicator.style.left = left + 'px';

View file

@ -44,9 +44,12 @@ canvas,
video,
iframe {
max-width: 100%;
height: auto;
font-style: italic;
vertical-align: middle;
&:not(.md-image) {
height: auto;
}
}

View file

@ -0,0 +1,36 @@
const getImageLightness = (image, onLoad) => {
let canvas = document.createElement('canvas');
image.onload = function() {
let colorSum = 0;
let ctx;
let imageData;
let imageMetadata;
let r;
let g;
let b;
let average;
canvas.width = this.width;
canvas.height = this.height;
ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0);
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
imageMetadata = imageData.data;
for (let x = 0, len = imageMetadata.length; x < len; x += 4) {
r = imageMetadata[x];
g = imageMetadata[x + 1];
b = imageMetadata[x + 2];
average = Math.floor((r + g + b) / 3);
colorSum += average;
}
onLoad(Math.floor(colorSum / (this.width * this.height)));
};
};
export default getImageLightness;

View file

@ -10,6 +10,7 @@ import MdChips from './components/mdChips';
import MdDialog from './components/mdDialog';
import MdDivider from './components/mdDivider';
import MdIcon from './components/mdIcon';
import MdImage from './components/mdImage';
import MdInputContainer from './components/mdInputContainer';
import MdLayout from './components/mdLayout';
import MdList from './components/mdList';
@ -40,6 +41,7 @@ const options = {
MdDialog,
MdDivider,
MdIcon,
MdImage,
MdInputContainer,
MdLayout,
MdList,