I am using fabric.js with Meteor.
I have the following SVG image which I am using as a pattern on a path within a path group.
As you can see there is some transparency to it.
What I wish to do is to fill a path with this pattern, and then use a color picker to be able to manipulate it's colour. I have been able to do this so far by adding the SVG as a pattern, and then duplicating the path and filling that with a colour with 50% opacity, but of course this changes the whole area colour, not just the patterns colour. Basically since the pattern is already a 'fill' of a path, how would I fill the pattern itself?
Here's a diagram to better explain...
Here's the code I am using to add the pattern when a particular pattern is selected from a dropdown list (using Meteor event)...
'change .shapeTopPattern': function(e, template){ e.preventDefault();
var textureID = e.target.value;
if(textureID != '') { //If this shape has a texture selected.
var texture = Textures.findOne(textureID);
//Get the image
var textureIMG = new Image;
textureIMG.crossOrigin = "anonymous";
textureIMG.src = texture.image;
var patternURL = textureIMG.src;
fabric.Image.fromURL(patternURL, function(img) {
var obj = canvas.getActiveObject();
var paths = obj.paths;
paths.forEach(function(p) {
if (p.pathName == "shapeTopTexture") {
img.width = p.width;
img.height = p.height
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
patternSourceCanvas.setDimensions({
width: p.width,
height: p.height
});
var texture = patternSourceCanvas.getElement();
var pattern = new fabric.Pattern({
source: texture,
repeat: 'no-repeat',
offsetX: p.width/2,
offsetY: p.height/2
});
obj.setFill();
if (obj instanceof fabric.PathGroup) {
p.fill = pattern;
obj.perPixelTargetFind = false;
} else {
obj.setFill(pattern);
}
canvas.renderAll();
}
});
});
}
},
This is the function I am using on a change event of the color picker. "shapeTopPatternColour" is the duplicated path (top of the cylinder) from the cylinder path-group. I know that this is obviously why the colour is going over the entire area instead of only the pattern, but it's the closest I got to what I wanted.
changeTopPatternColour = function(o, color, opacity) {
/*
* o = object
* color = rgbcolor data
* opacity = .5
*/
var paths = o.paths;
paths.forEach(function(p) {
if (p.pathName == "shapeTopPatternColour") {
p.setFill(color);
p.opacity = opacity;
}
});
canvas.renderAll();
};
So how can I...
Add the pattern and maintain it as an SVG (only if required)
Fill only the patterns alpha with colour and not transparent parts?
Thanks in advance.
Unfortunately I could not find a way to use as a pattern an svg file without having necessarily to rasterize it, I am sorry. In the example below you can see for yourself that I always entirely rewrite the surfaces.
Instead of loading the svg like an image, I load the svg normally and then I add it to the canvas using a pathgroup. For this snippet I am using your files as strings to avoid annoying CORS issues.
Here you can find the bitbucket repository
All the best.
$(function() {
var canvas = new fabric.Canvas('c');
canvas.setWidth(600);
canvas.setHeight(370);
var tint = function(color) {
canvas.clear();
var svgObjectString = '<?xml version="1.0" encoding="utf-8"?>' +
'<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"' +
' viewBox="0 0 596 366" style="enable-background:new 0 0 596 366;" xml:space="preserve">' +
'<style type="text/css">' +
'.st0{fill:#E0E0E0;}' +
' .st1{fill:url(#SVGID_1_);}' +
'</style>' +
'<path class="st0" d="M596,103.5c0,32-41.7,60.5-107.2,79.5c-51.7,15-118.2,24-190.8,24s-139.1-9-190.8-24C41.7,164,0,135.4,0,103.5' +
'c0-0.2,0-0.3,0-0.5C0.8,46.1,133.9,0,298,0s297.2,46.1,298,103C596,103.2,596,103.3,596,103.5z"/>' +
'<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="0" y1="133.25" x2="596" y2="133.25" gradientTransform="matrix(1 0 0 -1 0 368)">' +
'<stop offset="0" style="stop-color:#E8E8E8"/>' +
'<stop offset="0.23" style="stop-color:#878787"/>' +
'<stop offset="0.6" style="stop-color:#D6D6D6"/>' +
'<stop offset="1" style="stop-color:#ADADAD"/>' +
'</linearGradient>' +
'<path class="st1" d="M596,103.5v159c0,0.2,0,0.3,0,0.5c-0.8,56.9-133.9,103-298,103S0.8,319.9,0,263c0-0.2,0-0.3,0-0.5v-159' +
'c0,32,41.7,60.5,107.2,79.5c51.7,15,118.2,24,190.8,24s139.1-9,190.8-24C554.3,164,596,135.4,596,103.5z"/>' +
'</svg>';
fabric.loadSVGFromString(svgObjectString, function(svgobject) {
//fabric.loadSVGFromURL('../../Content/object.svg', function (svgobject) {
var objGroup = new fabric.PathGroup(svgobject, {
width: 596,
height: 500
});
canvas.add(objGroup);
var svgPatternString = '<?xml version="1.0" encoding="utf-8"?>' +
'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' +
'<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"' +
' width="576px" height="576px" viewBox="0 0 576 576" enable-background="new 0 0 576 576" xml:space="preserve">' +
'<polygon fill="#848484" points="290.664,286.625 244.214,729.625 338.422,729.625 "/>' +
'<polygon fill="#848484" points="290.711,286.625 337.16,-156.375 242.953,-156.375 "/>' +
'<polygon fill="#848484" points="290.688,286.602 -152.312,240.152 -152.312,334.359 "/>' +
'<polygon fill="#848484" points="290.688,286.648 733.688,333.098 733.688,238.89 "/>' +
'<polygon fill="#848484" points="290.664,286.625 244.214,729.625 338.422,729.625 "/>' +
'<polygon fill="#848484" points="290.711,286.625 337.16,-156.375 242.953,-156.375 "/>' +
'<polygon fill="#848484" points="290.688,286.602 -152.312,240.152 -152.312,334.359 "/>' +
'<polygon fill="#848484" points="290.688,286.648 733.688,333.098 733.688,238.89 "/>' +
'<polygon fill="#848484" points="290.666,286.616 75.532,676.646 162.318,713.297 "/>' +
'<polygon fill="#848484" points="290.709,286.634 505.843,-103.396 419.057,-140.047 "/>' +
'<polygon fill="#848484" points="290.696,286.604 -99.334,71.469 -135.984,158.255 "/>' +
'<polygon fill="#848484" points="290.679,286.646 680.709,501.78 717.359,414.994 "/>' +
'<polygon fill="#848484" points="290.671,286.608 -59.646,561.716 5.948,629.336 "/>' +
'<polygon fill="#848484" points="290.704,286.642 641.021,11.534 575.427,-56.086 "/>' +
'<polygon fill="#848484" points="290.704,286.609 15.597,-63.709 -52.024,1.885 "/>' +
'<polygon fill="#848484" points="290.671,286.641 565.778,636.958 633.398,571.364 "/>' +
'<polygon fill="#848484" points="290.679,286.603 -137.942,407.811 -102.993,495.296 "/>' +
'<polygon fill="#848484" points="290.696,286.647 719.315,165.439 684.367,77.954 "/>' +
'<polygon fill="#848484" points="290.709,286.617 169.502,-142.004 82.016,-107.055 "/>' +
'<polygon fill="#848484" points="290.666,286.634 411.873,715.253 499.358,680.305 "/>' +
'</svg>';
fabric.loadSVGFromString(svgPatternString, function(svgpattern) {
//fabric.loadSVGFromURL('../../Content/pattern.svg',
// function (svgpattern) {
svgpattern.map(function(item) {
item.fill = color;
});
var ptnGroup = new fabric.PathGroup(svgpattern, {
top: -190,
width: 596,
height: 500
});
var paths = objGroup.paths;
var path = paths[0];
svgpattern.width = path.width;
svgpattern.height = path.height;
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(ptnGroup);
patternSourceCanvas.setDimensions({
width: path.width,
height: path.height
});
var texture = patternSourceCanvas.getElement();
var pattern = new fabric.Pattern({
source: texture,
repeat: 'no-repeat',
offsetX: path.width / 2,
offsetY: path.height / 2
});
objGroup.setFill();
objGroup.globalCompositeOperation = "source-over";
path.setFill("#ff0000");
path.fill = pattern;
objGroup.perPixelTargetFind = false;
canvas.renderAll();
});
});
}
$('button')
.on('click',
function(e, args) {
tint(e.target.value);
});
});
canvas {
border: 1px solid #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.2/fabric.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="col-md-7">
<canvas id="c" style="border: solid 1px #ccc;"></canvas>
</div>
<div class="col-md-5">
<button class="btn-danger" value="red">red</button>
<button class="btn-success" value="green">green</button>
<button class="btn-primary" value="blue">blue</button>
</div>
</div>
</div>
Edit: to retrieve the dimensions of the top of your cylinder, I am using the first path of svgobject
var paths = objGroup.paths;
var path = paths[0];
svgpattern.width = path.width;
svgpattern.height = path.height;
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(ptnGroup);
patternSourceCanvas.setDimensions({
width: path.width,
height: path.height
});
Related
I'm using editor js (a block-style editor) for my app. You can install plugins for this editor to extend is functionality. On GitHub there is a math block plugin that I was trying to use there. But I can't get it to work. Hower here is my code:
First I include the plugin (which is the bundle.js on GitHub):
<script type="text/javascript" src="./plugins/editorjs/blocks/math.js"></script><!-- Math -->
Then I just folowed the normal setup (which worked for the other official plugins)
var editor = new EditorJS({
...
tools: {
...
Math: {
class: Math,
},
}
...
});
When I try to type something I get the error TypeError: Math.floor is not a function. Did I miss something?
Edit
https://flaming-cl.github.io/editorPlugin/
There is this example which works, but I don't understand it, there are so many files. I need more like a basic example with just the necessary CDN files.
Okey, I just remade the Plugin with Katex and it's working fine now. Here is my code, maybe it helps someone. Please keep in mind that this code may have bugs etc...
formala.js
class Formula {
static get toolbox() {
return {
title: 'Formula',
icon: '<?xml version="1.0" encoding="iso-8859-1"?>\r\n<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\r\n<svg version="1.1" id="fxicon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"\r\n\t width="15px" height="15px" viewBox="0 0 142.514 142.514" style="enable-background:new 0 0 142.514 142.514;"\r\n\t xml:space="preserve">\r\n<g>\r\n\t<g>\r\n\t\t<path d="M34.367,142.514c11.645,0,17.827-10.4,19.645-16.544c0.029-0.097,0.056-0.196,0.081-0.297\r\n\t\t\tc4.236-17.545,10.984-45.353,15.983-65.58h17.886c3.363,0,6.09-2.726,6.09-6.09c0-3.364-2.727-6.09-6.09-6.09H73.103\r\n\t\t\tc1.6-6.373,2.771-10.912,3.232-12.461l0.512-1.734c1.888-6.443,6.309-21.535,13.146-21.535c6.34,0,7.285,9.764,7.328,10.236\r\n\t\t\tc0.27,3.343,3.186,5.868,6.537,5.579c3.354-0.256,5.864-3.187,5.605-6.539C108.894,14.036,104.087,0,89.991,0\r\n\t\t\tC74.03,0,68.038,20.458,65.159,30.292l-0.49,1.659c-0.585,1.946-2.12,7.942-4.122,15.962H39.239c-3.364,0-6.09,2.726-6.09,6.09\r\n\t\t\tc0,3.364,2.726,6.09,6.09,6.09H57.53c-6.253,25.362-14.334,58.815-15.223,62.498c-0.332,0.965-2.829,7.742-7.937,7.742\r\n\t\t\tc-7.8,0-11.177-10.948-11.204-11.03c-0.936-3.229-4.305-5.098-7.544-4.156c-3.23,0.937-5.092,4.314-4.156,7.545\r\n\t\t\tC13.597,130.053,20.816,142.514,34.367,142.514z"/>\r\n\t\t<path d="M124.685,126.809c3.589,0,6.605-2.549,6.605-6.607c0-1.885-0.754-3.586-2.359-5.474l-12.646-14.534l12.271-14.346\r\n\t\t\tc1.132-1.416,1.98-2.926,1.98-4.908c0-3.59-2.927-6.231-6.703-6.231c-2.547,0-4.527,1.604-6.229,3.684l-9.531,12.454L98.73,78.391\r\n\t\t\tc-1.89-2.357-3.869-3.682-6.7-3.682c-3.59,0-6.607,2.551-6.607,6.609c0,1.885,0.756,3.586,2.357,5.471l11.799,13.592\r\n\t\t\tL86.647,115.67c-1.227,1.416-1.98,2.926-1.98,4.908c0,3.589,2.926,6.229,6.699,6.229c2.549,0,4.53-1.604,6.229-3.682l10.19-13.4\r\n\t\t\tl10.193,13.4C119.872,125.488,121.854,126.809,124.685,126.809z"/>\r\n\t</g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n<g>\r\n</g>\r\n</svg>'
};
}
constructor({data}){
this.data = data;
}
render(){
this.wrapper = document.createElement('div');
const input = document.createElement('input');
const inner = document.createElement('div');
this.wrapper.classList.add('formula-block');
this.wrapper.appendChild(inner).classList.add('inner-formula-wrapper');
this.wrapper.appendChild(input).classList.add('cdx-input');
input.placeholder = 'Enter a LaText formala here...';
var value = this.data && this.data.text ? this.data.text : '';
input.value = value;
//.replace(/\\/g,"\\\\");
this._createFormala(this.data && this.data.text ? this.data.text : 'eqation: ');
var eventList = ["change", "keyup", "paste", "input", "propertychange", "..."];
for(event of eventList) {
input.addEventListener(event, (event) => {
this._createFormala(input.value.replace(/\$/g, ''));
});
}
inner.onclick = function() {
this.closest('.formula-block').classList.toggle('is-edit');
}
return this.wrapper;
}
_createFormala(text){
const input = document.createElement('input');input.value = text;
var rendered_formula = katex.renderToString(text, {
throwOnError: false
});
input.placeholder = 'Caption...';
this.wrapper.getElementsByClassName('inner-formula-wrapper').item(0).innerHTML = rendered_formula;
}
save(blockContent){
const input = blockContent.querySelector('input');
return {
text: input.value.replace(/\$/g, '')
}
}
validate(savedData){
if (!savedData.text.trim()){
return false;
}
return true;
}
}
Tools list config
var editor = EditorJS({
...
tools: {
...
formula: Formula,
}
...
});
Load the Katext Files and formala.js
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex#0.12.0/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
<script defer src="https://cdn.jsdelivr.net/npm/katex#0.12.0/dist/katex.min.js" integrity="sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4" crossorigin="anonymous"></script>
<script type="text/javascript" src="./plugins/editorjs/blocks/formula.js"></script><!-- Formula -->
Data Input Usage
{
"type": "formula",
"data": {
"text": '\\pm\\sqrt{a^2 + b^2} \\newline a ',
}
},
Hi I am having an angular 5 project . I am drawing an bar graph using d3js library. In my bar graph there are vertical bars to which I would like to apply styles. However it is not working as the bars are displayed with default black colour as show below.
The following is my component html code, where i have a div tag named "histogramHolder" to which i will append the svg from my component ts file.
performance.component.html
<div class="row">
<div class="col-1"></div>
<div class="col-10" id="histogramHolder">
</div>
<div class="col-2"> </div>
</div>
the following is my component scss file.
performance.component.scss
.bar {
fill: steelblue;
}
the following is the code snippet where i create an svg image and append to the div tag named "histogramHolder"
import * as d3 from "d3";
#Component({
selector: 'pc-performance',
templateUrl: './performance.component.html',
styleUrls: ['./performance.component.scss']
})
export class PerformanceComponent implements OnInit {
ngOnInit() {
const data=[{"key":"2019-09-11","documentCount":149002},{"key":"2019-09-12","documentCount":0},{"key":"2019-09-13","documentCount":80000},{"key":"2019-09-14","documentCount":0},{"key":"2019-09-15","documentCount":0},{"key":"2019-09-16","documentCount":0},{"key":"2019-09-17","documentCount":0},{"key":"2019-09-18","documentCount":270204},{"key":"2019-09-19","documentCount":0},{"key":"2019-09-20","documentCount":1},{"key":"2019-09-21","documentCount":0},{"key":"2019-09-22","documentCount":0},{"key":"2019-09-23","documentCount":269836},{"key":"2019-09-24","documentCount":0},{"key":"2019-09-25","documentCount":0},{"key":"2020-01-15","documentCount":0},{"key":"2020-01-16","documentCount":0},{"key":"2020-01-17","documentCount":0},{"key":"2020-01-18","documentCount":0},{"key":"2020-01-19","documentCount":0},{"key":"2020-01-20","documentCount":0},{"key":"2020-01-21","documentCount":0},{"key":"2020-01-22","documentCount":0},{"key":"2020-01-23","documentCount":0},{"key":"2020-01-24","documentCount":0},{"key":"2020-01-25","documentCount":0},{"key":"2020-01-26","documentCount":0},{"key":"2020-01-27","documentCount":0},{"key":"2020-01-28","documentCount":0},{"key":"2020-02-09","documentCount":0},{"key":"2020-02-10","documentCount":56000},{"key":"2020-02-11","documentCount":500}];
const margin = {top: 20, right: 20, bottom: 60, left: 60},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
const x = d3.scaleBand().range([0, width]).paddingInner(0.1).paddingOuter(0.5);
const y = d3.scaleLinear().range([height, 0]);
const svg = d3.select("div#histogramHolder").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
x.domain(data.map(function(d) { return d.key; }));
y.domain([0, d3.max(data, function(d) { return d.documentCount; })]);
// append the rectangles for the bar chart
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.key); })
.attr("width", x.bandwidth())
.attr("y", function(d) { return y(d.documentCount); })
.attr("height", function(d) { return height - y(d.documentCount); });
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("y", 0)
.attr("x", 9)
.attr("dy", ".35em")
.attr("transform", "rotate(60)")
.style("text-anchor", "start");
// add the y Axis
svg.append("g").call(d3.axisLeft(y));
}
}
I would expect the bars to be displayed in steelblue colour as i am setting it ( .attr("class", "bar") ) in the code . however it is not happening
appreciate any help
Any content that is added in DOM by library then customized css of dynamically added element will not applied if it is in component's css. So it's necessary to add customized css in Global style.
Try to put style of svg in your globle style styles.scss
So, here is a custom directive to resize an element and it's contents based on a screen size change. I can see that the value of 'scalify' is changing how I would like it to, but the style itself is not changing. I know that the styles work when applied with static values directly in the css file.
.directive("card", function(){
return{
restrict : "E",
controller: function($scope, $element, $attrs){
var w = this;
window.onresize = function () {
$scope.scalify = {
'-ms-zoom': window.innerHeight/675,
'-moz-transform': 'scale(' + window.innerHeight/675 + ')',
'-o-transform': 'scale(' + window.innerHeight/675 + ')',
'-webkit-transform': 'scale(' + window.innerHeight/675 + ')'
};
$scope.$apply();
}
}
};
})
And here's how I use the ng-Style in the HTML
<card ng-style="scalify">
...
</card>
Hi please see here: http://run.plnkr.co/jfeF9NcPcGroNCsg/ probably you need to work a bit on your css transformation but style is changing when you change size of window as you wanted
app.directive("card", function($window) {
return {
restrict: "E",
link: function(scope, element, attrs) {
scope.onResizeFunction = function() {
//$scope.windowHeight = $window.innerHeight;
// $scope.windowWidth = $window.innerWidth;
var scalify = {
'-ms-zoom': $window.innerHeight / 675,
'-moz-transform': 'scale(' + $window.innerHeight / 675 + ')',
'-o-transform': 'scale(' + $window.innerHeight / 675 + ')',
'-webkit-transform': 'scale(' + $window.innerHeight / 675 + ')',
'background-color': 'red'
};
element.css(scalify);
console.log(element);
};
angular.element($window).bind('resize', function() {
scope.onResizeFunction();
scope.$apply();
});
}
}
});
I am using JCrop to crop an image after upload with Ajax upload
control in my web application. It works great on Chrome, Firefox but
not in IE. I use JCrop v0.9.12 (build: 20130202) and IE
v10.0.9.9200.16635. Problem is JCrop selection doesn't work in IE.
Thanks!
Here is my scripts.
<script type="text/javascript">
jQuery(document).ready
(function ($) {
// To hold the API and image size.
var jcrop_api, boundx, boundy;
$('#<%=imgCrop.ClientID%>').Jcrop (
{ // img_crop is the ID of image control
onChange: updatePreview, // will display the selected img on change.
onSelect: updatePreview, // will display the selected img Img_preview
onSelect: storeCoords, // will tell the coordinates
aspectRatio: 11 / 15
}, function ()
{
jcrop_api = this;
var bounds = this.getBounds();
boundx = bounds[0];
boundy = bounds[1];
}
);
function updatePreview(c) {
if (parseInt(c.w) > 0) {
var rx = 100 / c.w;
var ry = 100 / c.h;
$('#<%=Img_preview.ClientID%>').css({ //Img_preview is the ID of image control
width: Math.round(rx * boundx) + 'px',
height: Math.round(ry * boundy) + 'px',
marginLeft: '-' + Math.round(rx * c.x) + 'px',
marginTop: '-' + Math.round(ry * c.y) + 'px'
});
}
};
});
// will store the selected part the images coordinates
function storeCoords(c) {
jQuery('#<%=W.ClientID%>').val(c.w);
jQuery('#<%=H.ClientID%>').val(c.h);
jQuery('#<%=X.ClientID%>').val(c.x);
jQuery('#<%=Y.ClientID%>').val(c.y);
};
</script>
A common fix for IE is to do
$.Jcrop('#<%=imgCrop.ClientID%>', {
// your inits
});
I am using ExtJs 4, and added a grid to show my records. Grid is also showing images on each row. To show images I am using templatecolumn xtype. There can be one or two images for each record. its {id}_original.{extension} or {id}.{extension}.
My problem is that if there is just one image, I want to show it in two field on the grid.
Here is my code:
Grid Columns Definition
columns: [
{
text: 'ID',
hideable: false,
dataIndex: 'id'
},
{
xtype: 'booleancolumn',
text: 'Aktif mi?',
dataIndex: 'publishableFlag',
trueText: 'Evet',
falseText: 'Hayır'
},
{
text: 'Kullanıcı',
dataIndex: 'ownerName'
},
{
text: 'Yükseklik',
dataIndex: 'fileHeight'
},
{
text: 'Genişlik',
dataIndex: 'fileWidth'
},
{
text: 'Ürün',
dataIndex: 'productId'
},
{
text: 'Orjinal Fotoğraf',
xtype:'templatecolumn',
flex: 1,
tpl: '<img src="'+path+'{id}_original.{fileExtension}" height=100 width=100 />'
//checkImageExist(path + '{id}_original.{fileExtension}', this) ? '<img src="'+path+'{id}.{fileExtension}" height=100 width=100 />' : 'noldu yaa'
},
{
text: 'Güncellenen Fotoğraf',
xtype:'templatecolumn',
flex: 1,
tpl: '<img src="http://www.kaft.com/static/images/photos/{id}.{fileExtension}" height=100 width=100 />'
}
]
Here is code to check if an image exit
function checkImageExist(url, d)
{
console.log(url, d);
var img = new Image();
img.src = url;
return img.height != 0;
}
I don't need to write rest of the code.
You should be able to do it in two ways.
Either use a plain renderer:
{
text: 'Orjinal Fotoğraf',
flex: 1,
renderer: function ( aValue, aMetaData, aRecord ) {
return checkImageExist( path + aRecord.id + '_original.' + aRecord.fileExtension, this) ? '<img src="'+path+ aRecord.id + '.' + aRecord.fileExtension + '" height=100 width=100 />' : 'noldu yaa';
}
Or user an Xtemplate, something roughly like this:
this.MyTpl = new Ext.XTemplate (
'<img src="'+path+'{id}_original.{fileExtension}" height=100 width=100 />[this.checkImageExist( values.url, values.d )]'
{
disableFormats: true,
checkImageExist: function ( aUrl, aD )
{
console.log( aUrl, aD );
var img = new Image();
img.src = aUrl;
return img.height != 0 ? '<img src="'+path+'{id}.{fileExtension}" height=100 width=100 />' : 'noldu yaa'
}
}
);