Utility component create a proportionally-sized element, into which other elements can be displayed
Vue.component('ratio', {
template:'<div class="ratio" :style="style"><slot></slot></div>',
props:
{
width:
{
default :512,
type :[String, Number],
required :true
},
height:
{
default :288,
type :[String, Number],
required :true
},
size:
{
type :[Number, String, Object, Array]
},
aspect:
{
default :16/9,
type :[String, Number]
}
},
data:function()
{
return {w:this.width, h:this.height, a:this.width / this.height};
},
computed:
{
width:
{
get:function(){ return this.w; },
set:function(value)
{
value = parseFloat(value);
this.w = value;
this.h = value / this.a;
}
},
height:
{
get:function(){ return this.h; },
set:function(value)
{
value = parseFloat(value);
this.h = value;
this.w = value * this.a;
}
},
size:
{
get:function(){ return {width:this.w, height:this.h}; },
set:function(value)
{
if(typeof value == 'number' || typeof value == 'string')
{
this.w = this.h = parseFloat(value);
}
else if(value instanceof Array)
{
this.w = value[0];
this.h = value[1];
}
else
{
this.w = value.width;
this.h = value.height;
}
this.a = this.w / this.h;
}
},
aspect:
{
get:function(){ return this.a; },
set:function(value)
{
if(typeof value == 'number')
{
this.a = value;
}
else
{
var parts = value.match(/\d+/g);
this.a = parseInt(parts[0]) / parseInt(parts[1]);
}
this.width = this.w;
}
},
style:function()
{
return {width:this.w + 'px', height:this.h + 'px'};
}
}
});