I am trying to dynamically change the border color of some of my shapes based on a cell's custom attribute, following is my code:
var cells = graph.getChildCells();
for (var i = 0; i < cells.length; i++) {
var cell = cells[i];
if (cell != null && ....) {
var style=cell.getStyle();
console.info('style='+style);
style=style+mxConstants.STYLE_STROKECOLOR+"=red";
cell.setStyle(style);
console.info('style='+style);
}
}
In the browser's console I see:
style=ellipse;whiteSpace=wrap;rotation=40;
style=ellipse;whiteSpace=wrap;rotation=40;strokeColor=red
but nothing happen. Is it the right approach ?
I found the answer by myself ;-) Following is the working code to change the stroke color without modify other settings/styles of the shape:
var style=graph.getModel().getStyle(cell);
var newStyle=mxUtils.setStyle(style,mxConstants.STYLE_STROKECOLOR,'red');
var cs= new Array();
cs[0]=cell;
graph.setCellStyle(newStyle,cs);
I think it is little bit tricky compared to what it does but I didn't find better API than these.
There is a better way.
graph.setCellStyles(mxConstants.STYLE_STROKECOLOR, 'red', [cell])
Check mxGraph documentation here
Related
Is it possible to add custom materials to each side of a polygon if it is created by calling viewer.dataSources.add(data) ?
I was originally using the extrudedHeight property to set different heights of my objects, but I learned that this limits the ability to set a material on any side except for the top of the polygon.
If I select the entity afterwards using the entities.getById function, I am able to reset the extrudedHeight property to 0, and THEN set the height property of the polygon which allows it to keep the same height without relying on the extrudedHeight property. As far as I can tell, however, the entity still behaves the same way when I try to set the material again.
Is there no difference between the height and extrudedHeight properties? In any case, is there a way that I can have my custom material on the outter edges of the polygon, rather than the top, without having to build a custom polygon for each of my objects (which, in this case, are buildings)?
My code:
var viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider : new Cesium.createOpenStreetMapImageryProvider({
url : 'http://tile.stamen.com/watercolor/'
}),
baseLayerPicker : false
});
var dataSource = Cesium.GeoJsonDataSource.load('../data/mDataSource.json').then(function(data) {
viewer.dataSources.add(data);
viewer.zoomTo(data);
var entities = data.entities.values;
var colorHash = {};
for (var i = 0; i < entities.length; i++) {
var entity = entities[i];
var name = entity.name;
var color = colorHash[name];
if (!color) {
color = Cesium.Color.fromRandom({
alpha : 1.0
});
colorHash[name] = color;
}
entity.polygon.material = '../data/img/myMaterial.png';
entity.polygon.extrudedHeight = 10;
}
var mEntity = viewer.dataSources.get(0).entities.getById("mId");
mEntity.polygon.extrudedHeight = 0;
mEntity.polygon.height = 10;
mEntity.polygon.material = '../data/img/myMaterial.png';
});
EDIT: I've also heard that in order to achieve what I'm looking for, I would need to design my own custom polygon. If this is the case, is it possible to use custom polygons with data sets brought in through the Cesium.GeoJsonDataSource method?
I am applying filters to a bitmap using something like:
TweenLite.to(origBitmap,0,{colorMatrixFilter:{saturation:2,brightness:3});
and that works fine.
I need to somehow apply a sharpen filter to origBitmap which I have successfully achieved using a ConvolutionFilter. The problem is after I've ran the above tweenlite call, then create a convolution filter and apply it to origBitmap, it removes the initial saturation and brightness filters and just keeps the sharpen filter
private function applyEffects(effects:Array):void
{
currentEffects = effects;
var props:Object = {};
for (var i:String in effects)
{
props[effects[i].effect] = effects[i].amount;
}
TweenLite.to(bitmap,0,{colorMatrixFilter:props});
//-- props could look like {saturation:2,brightness:3}
//-- This will sharpen the container sprite
var matrix:Array = [0, -1, 0,
-1, 5, -1,
0, -1, 0];
var conv:ConvolutionFilter = new ConvolutionFilter();
conv.matrixX = 3;
conv.matrixY = 3;
conv.matrix = matrix;
conv.divisor = 1;
bitmap.filters = [conv]; //-- this removes the above filters and just sharpens the image
}
Is there a way to also incorporate the ConvolutionFilter in that TweenLite call above? I've searched quite a bit and found some guy made a class called TweenMan which was based around your class where ConvolutionFilter is incorporated: https://github.com/danro/tweenman-as3
Nothing to do with TweenMax here since your code is the one making the mistake. This correctly removes all current filter and apply only one:
bitmap.filters = [conv];
Since filters property is either null or is an Array. To add a filter to the list you use array operation and reapply the array:
var filters:Array = bitmap.filters;
if(!filters)
{
filters = [];
}
filters.push(conv);
bitmap.filters = filters;
EDIT: starting over since I think I understand what you are trying to do. You are avoiding creating the filter yourself and let TwennLite do it for you even tough you don't need to tween anything. Don't do that, you are making everything harder for yourself. Instead create your filter that way:
var props:Object = {};
var colorMatrix:ColorMatrixFilter = new ColorMatrixFilter();
for (var i:String in effects)
{
colorMatrix[effects[i].effect] = effects[i].amount;
}
bitmap.filters = [colorMatrix];
//etc .... then
var filters:Array = bitmap.filters;
filters.push(conv);
bitmap.filters = filters;
If you need to animate multiple filters remember that most tween engine can tween easily array values so you can just do that and then apply those array values to your filters.
I want to swap a bitmap in symbol with another bitmap,and I found the the function
swapElement
This is what I have tried
var elements = item.timeline.layers[0].frames[0].elements;//item is the symbol
for (var j = 0; j < elements.length; j++) {
var el = elements[j];
if (el.instanceType == "bitmap") {
el.selected = true;//this line not work, so I want a way to make the element selected
dom.swapElement(targetName);//targetName is another bitmap name that I wanted
}
}
Setting selected to true of an element, will only select the element if the element is on screen (and the layer is unlocked and visible). So before selected is set to true library.editItem(item.name) should be called. If the element is in frame x, frame x has to be made the current frame with document.getTimeline().setSelectedFrames(parseInt(x), parseInt(x) + 1, true). (I use parseInt(x) as a cast because of a bug in setSelectedFrames). To be sure the element is the only element that is selected document.selectNone() should be called before setting selected to true.
Every instance has a libraryItem so maybe replacing the libraryItem is easier.
The code here can be adapted for a more selective replace.
From library? Then following snippet could help you
var libItems = fl.getDocumentDOM().library.items;
for (i = 0; i < libItems.length; i++){
if(libItems[i].itemType == “bitmap”){
//found bitmap :)
}
OK, what about:
fl.selectElement(el); //instead of el.selected = true;
dom.swapElement(targetName);//assuming you have targetName
This works if there is anything (one item) selected that is bitmap it will replace it with library item named "image4":
var dom = fl.getDocumentDOM();
var selection = dom.selection;
if(selection.length == 1 && selection[0].instanceType == "bitmap")
{
dom.swapElement("image4");
}
I'd like to be able to alter an image (specifically a bitmap) in order to replace all dark grey and black pixels with white in ActionScript 3, but maintain all other colors in the image. I am familiar with ColorMatrixFilter and bitmapdata.threshold, but I don't know how to use them to either target the colors I want to remove or check within a specific range of colors. Is there any (efficient) way to go about doing this?
Thanks for any help you can offer.
The AS3 API gives pretty good documentation on how to use the treshhold value. You can find it here. Their example actually checks for a certain range of colors. I've modified their example to work for your problem. I haven't tested it, so it might need some tweaking.
var bmd2:BitmapData = new BitmapData(200, 200, true, 0xFFCCCCCC);
var pt:Point = new Point(0, 0);
var rect:Rectangle = new Rectangle(0, 0, 200, 200);
var threshold:uint = 0x00A9A9A9; //Dark Grey
var color:uint = 0x00000000; //Replacement color (white)
var maskColor:uint = 0xFFFFFFFF; //What channels to affect (this is the default).
bmd2.threshold(bmd1, rect, pt, ">", threshold, color, maskColor, true);
Another option would be to use a double for loop that iterates over all pixels and takes a certain action based on the value of the pixel.
for(var y:int = 0; y < height; y++){
for(var x:int = 0; x < width; x++){
var currentPixel:uint = image.getPixel( x, y );
if(currentPixel != color){
image.setPixel( destPoint.x + j, destPoint.y + i, currentPixel );
}
}
}
Is there an efficient way to get a list of colors of what is currently drawn in an HTML Canvas?
I guess the correct term would be a Color Palette of the current composite
Assume you have an html document like the following:
<canvas id="example" width="500" height="300"></canvas>
<ul id="list">
<h3>Click the canvas to extract colors</h3>
</ul>
I have created a fiddle in which you have a ready made canvas with some shapes and colors that we will be processing when we click on it. I'm not creating a color picker for you, just listing as that was the original answer and should serve as the means to achieve the second part of it.
Here's the fiddle
The function that extracts the colors an lists them is the following, I'm avoiding copying all the canvas drawing stuff since it just serves as the example and isn't generic enough.
var colorList = []; //This will hold all our colors
function getColors(){
var canvas = document.getElementById('example');
var context = canvas.getContext('2d');
var imageWidth = canvas.width;
var imageHeight = canvas.height;
var imageData = context.getImageData(0, 0, imageWidth, imageHeight);
var data = imageData.data;
// quickly iterate over all pixels
for(var i = 0, n = data.length; i < n; i += 4) {
var r = data[i];
var g = data[i + 1];
var b = data[i + 2];
//If you need the alpha value it's data[i + 3]
var hex = rgb2hex("rgb("+r+","+g+","+b+")");
if ($.inArray(hex, colorList) == -1){
$('#list').append("<li>"+hex+"</li>");
colorList.push(hex);
}
}
}
This will produce a result containing a seemingly unordered list of hex values that represent the order in which they appear in your image (hence the 'seemingly'), if you want a color picker however you may want to consider the use of colorList.sort(); which will order the array into a black-to-white fashion.
Note that I'm using the rgb2hex function to convert the values returned to the hex format I'm assuming your wanting, if you're ok with rgb feel free to not use it, the function is the following:
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
And the source is this, as I stated as a comment in the code, you could easily extract the alpha channel too if you needed to but I went for the most generic scenario (and simplest) that I could think of.